Docs
Agent

Turn Context and Isolation

Explains how each agent turn is trust-isolated — the delegated JWT scope the agent receives, the call-back architecture where all tool calls route through markdocket-api, and why the agent worker holds no direct database access or worker API keys.

The MarkDocket agent is a stateless, trust-isolated microservice. Every agent turn operates within a narrow, user-scoped permission boundary enforced by delegated credentials, a durable turn state machine, and an architecture that routes all data access back through markdocket-api rather than allowing direct connections to any data store or sibling service.

How the Agent Receives Its Turn Credentials

When you start an agent turn, markdocket-api acts as the trust broker:

  1. Your session (cookie, API key, or OAuth token) is authenticated by markdocket-api.
  2. markdocket-api mints a delegated JWT scoped to your user identity for that turn and forwards it to the agent worker alongside the turn request.
  3. The agent worker uses this delegated token — carried as X-Delegated-Token — for every tool call it makes during that turn.

The agent worker never sees your original session credential. It receives only the delegated token, whose scope is bounded to what markdocket-api determines you are authorized to do.

Automation agent nodes follow the same pattern

Automation runs that include agent nodes mint a fresh delegated token per execution inside the durable Inngest function. No credential is carried over between automation runs or agent sessions.

Tool Calls Always Route Back Through the API

The agent worker holds no direct connections to:

  • The Neon Postgres database
  • The USPTO worker
  • The brand-intel worker
  • Stripe or any billing system
  • Any other sibling service

Every tool in the agent's registry calls back to markdocket-api using the delegated JWT. markdocket-api then re-dispatches the request to the appropriate worker or data source, enforcing its own authorization and metering checks on each call.

This means the agent's blast radius is structurally bounded: compromising the agent worker process exposes only what the current delegated token permits — not worker API keys, database credentials, or any other service secrets.

Your browser or client


  markdocket-api          ← authenticates you, mints delegated JWT

        │  X-Delegated-Token

  markdocket-agent        ← runs the LLM turn loop

        │  tool call with X-Delegated-Token

  markdocket-api          ← validates token, re-dispatches to workers


  USPTO worker / brand-intel worker / Neon DB / ...

The Turn State Machine

Every agent interaction is tracked as a durable turn in the database, progressing through the following states:

StateMeaning
authorizingBilling reservation is being created
authorizedReservation confirmed; file uploads may begin
uploadingAttached files are being committed to the turn
runningThe LLM loop is active
completedTurn finished successfully
deniedAuthorization or billing reservation failed
failedAn error terminated the turn
expiredThe turn timed out before completion
cancelledThe turn was explicitly cancelled

State transitions use compare-and-swap (CAS) operations, so no two concurrent processes can advance the same turn to conflicting states. A background sweep releases any billing reservation and cleans up orphaned files for turns that reach expired without completing.

Billing Is Pre-Authorized Before Any Work Starts

The transition from authorizing to authorized is atomic with the creation of a billing reservation. No file upload or message commit is permitted until this reservation exists. This means:

  • The agent loop cannot start without confirmed billing authorization.
  • If authorization fails, the turn moves to denied immediately and no LLM call is made.

File Uploads Within a Turn

Files attached to an agent turn are scoped to that turn and validated against the active billing reservation before being committed. Upload identifiers are derived deterministically from the turn identity and an idempotency key, so re-submitting the same file under the same key produces the same result without a redundant database check.

All attachments are stored in Vercel Blob and referenced from the turn record — the agent worker fetches image URLs from Blob for multimodal processing but does not write to any persistent store directly.

Why the Agent Has No Direct Database Access

The isolation is intentional and architectural, not a configuration choice:

  • markdocket-api is the sole writer to the Neon Postgres database across the entire platform. No other service — including the agent worker — holds database credentials.
  • All agent actions that produce persistent side effects (saving messages, updating portfolios, filing submissions) go through markdocket-api endpoints, which enforce authorization, idempotency, and audit logging.
  • Every agent action is recorded in the markdocket-api database (agent sessions, messages, and attachments), giving you a complete audit trail that the agent worker itself cannot alter.

Billing Events and the Agent

The agent worker emits product usage events — it does not emit provider cost (COGS) events. Provider cost accounting for LLM calls is handled by markdocket-api for calls it makes directly, and by the BYOK worker for Bring Your Own Key automation runs. This separation prevents double-counting in multi-service billing scenarios.

If a tool call result indicates that a billing limit has been reached, the agent streams a billing_required SSE event back to the client. This event carries a structured BillingBlockEnvelope that the web app intercepts and surfaces as an upgrade or action prompt — the turn stops cleanly rather than failing with an unhandled error.

BYOK keys are not available to interactive agent chat

Bring Your Own Key (BYOK) AI provider credentials are scoped exclusively to agent nodes inside Automation Runs. They are never used for interactive agent chat turns, draft workflows, or any direct LLM call made by the API server.

Trust Boundary Summary

What the agent worker can doWhat the agent worker cannot do
Use the delegated JWT to call markdocket-api endpoints on your behalfHold or use worker API keys (USPTO, brand-intel, etc.)
Run tool calls within your authorized scopeConnect to the database directly
Stream SSE events (text, tool calls, billing blocks) back to the API proxyWrite to any persistent store without going through markdocket-api
Fetch image URLs from Blob for multimodal turnsAccess your session credential or original auth token
Emit product usage billing eventsEmit provider COGS billing events

This architecture means that the agent's capabilities are always a strict subset of your own permissions, enforced at the API layer on every tool call — not just at the start of the turn.

On this page