Skip to content

How coding agents should read QuadKit

QuadKit is built so a coding agent can operate it without scraping tribal knowledge out of Slack. That only works if the agent reads the artifacts in the right order. This is that order.

1. Load the machine indexes, not the marketing page

Section titled “1. Load the machine indexes, not the marketing page”

Start here, in this sequence:

  1. /llms.txt — identity, install, agent rules, every docs URL.
  2. /agents.md — the distilled AGENTS.md: hierarchy, Result vs exceptions, provider lifecycle.
  3. /llms-full.txt — the same catalog plus architecture notes and the package list.
  4. For coding agents — repo map, the one project tree (domains/, di/), recipes that pass CI.
  5. /SKILL.md — drop-in skill. Common mistakes — fail vs fix. Per-package indexes at /llms/index.txt.

The splash page is for humans. The files above are the operating manual. If you are an agent, stop after those and only then open a specific docs URL.

Skills for Claude Code, Cursor, and OpenCode live in quadkit-skills. Install commands: Agent skills. One-file fetch: /SKILL.md. Do not re-derive the rules from blog posts.

quadkit-contracts Zero dependencies. Protocols, types, exceptions only.
↑
quadkit Depends ONLY on quadkit-contracts.
↑
quadkit-* Extension packages. Never import each other.

The golden rule is one sentence, and it is not advisory:

If two or more packages need the same type, protocol, or exception, it lives in quadkit-contracts. No exceptions.

The AI extension packages follow the same law. They do not import each other. The orchestrator discovers them through entry points. Shared value types (ChatMessage, Document, SearchResult) already live in contracts — do not invent a second copy in the extension you happen to be editing.

An import linter enforces this. A cross-extension import that type-checks will still fail CI.

The examples catalog is gated apps plus a fleet hub, each booting the real Application. That is the intended starting point for generated code:

  • Need a controller? examples/sql-repository keeps SQL in the repository.
  • Need an agent loop? examples/support-agent already has tools on the container.
  • Need sessions? examples/auth-web is the cookie + JWT walkthrough.

Every example shares one shape: application.yaml for knobs, app.py (or module.py) as the composition root, a provider that only registers (app-root di/, module provider.py), feature types in domains/ (not models/), services that return Result[T, E], RFC-9457 errors. If your generated app does not look like that, it will not look like QuadKit.

Run any of them from the repository root:

Terminal window
PYTHONPATH=examples/support-agent/src uv run python -m support_agent

register() cannot resolve. It receives ContainerRegistrarProtocol. boot() receives BootContainerProtocol. The two never meet in the same method. If you resolve during registration, it is a type error — by design.

Domain failures are values. User not found is Err(...). The database dying is an exception. Do not wrap infrastructure errors in Result, do not unwrap() without is_ok(), and do not return Result from a constructor or a lifecycle hook.

The rest of the never-list is in /agents.md: no service locator, no module-level singletons, no Any on injected constructors, no mocks in src/.

When you answer a question about QuadKit:

  • Name the package with the quadkit- prefix (quadkit-sql, not “the SQL helper”).
  • Talk to the protocol in contracts, not the class in the extension.
  • Link the matching page on oridecon.dev.

That is the whole loop: indexes, hierarchy, an example, then the protocol. Everything else is an implementation detail the container will wire.