Architecture

The one canonical execution path Kaji uses to run a capability, and the boundaries it does and does not own.

Execution Path

kaji.execute(capability, request) is the only way a capability runs. There is no second path, so no caller can accidentally skip a safety boundary. For one request, the executor:

  1. Validates principalId and idempotencyKey are non-empty strings.
  2. Validates input against the capability’s input.parse().
  3. Claims the idempotency key in the execution store. An existing claim returns the same recorded or in-flight outcome instead of running execute again; a conflicting claim (same key, different input, capability, or principal) settles failed.
  4. Calls authorize({ principalId, input }). A false result or a thrown error settles denied.
  5. If approval({ principalId, input }) returns true, calls the configured approve handler. A missing handler, an invalid decision, a rejected decision, or a handler error settles rejected.
  6. Calls execute(input, context) at most once.
  7. Records the outcome in the execution store and returns it.

Cancellation is checked before each step that hasn’t yet started a side effect; once execute has been called, Kaji can no longer prove the action didn’t begin, so every failure path from that point settles unknown rather than an ordinary failure.

request
  → validate input
  → claim idempotency key
  → authorize
  → approve (if required)
  → execute            (side effects may begin here)
  → record outcome

Boundaries

Kaji owns the execution boundary; it does not own what’s on either side of it.

  • Capability code is ordinary application code. execute, authorize, and approval are functions your application supplies. Kaji never contains business logic, and it never calls a capability’s functions outside kaji.execute().
  • The execution store is a narrow contract. It claims idempotency keys atomically and records terminal outcomes. It is not a general event log, and v0 ships only memoryStore(), a process-local, non-durable implementation. A production deployment supplies its own durable ExecutionStore.
  • Approval is a decision, not a UI. Kaji calls the approve handler you configure and enforces its decision; it does not implement a review queue, notification system, or audit UI.
  • Cancellation and timeout use native AbortSignal. Kaji combines the caller’s signal with its own timeoutMs into one effective signal; it does not invent a Kaji-specific cancellation token.

Footnotes

Kaji has no agent loop, model provider, tool registry, session or event store, CLI, or hosted control plane. An agent framework, MCP server, or direct application code decides what action to request; Kaji only governs how that one action is safely executed. See docs/product.md in the repository for the complete non-goal list.

Further Reading