# Define, test and inspect an agent > Publish a version, admit a bounded run and inspect verified outputs. Section: Synapse and Locus. Web page: https://docs.katara.com/products/runs/ [Tutorial: run a managed agent](https://docs.katara.com/products/tutorial-managed-agent.txt) takes the shortest path through this page, as a free simulation. [Product availability](https://docs.katara.com/products/availability.txt#managed-execution) says how to tell whether runs execute where you call them. A Synapse agent version pins its instructions, input and output schemas, model policy, tool versions, knowledge collections, approval policies and execution limits. Editing a definition creates another version. An existing run keeps the version it was admitted against. Whether runs execute where you call them depends on the execution and storage services enabled for your environment. Confirm that paid compute is enabled before using Test Compute or Live. A queued run confirms admission; it does not confirm that a worker has started. ## Publish a definition [Create a managed agent identity](https://docs.katara.com/products/agent-identities.txt), then upload and approve the instructions and JSON schemas. `getAgentDefinitionState` returns the latest published version, or `null` for an identity without one. Use that revision as `expected_version` when calling `publishAgentVersion`; use zero for the first version. Instructions accept plain text or Markdown up to 128 KiB. Each schema is JSON up to 256 KiB. The definition names explicit maximums for steps, decisions, plan changes, child agents, depth, active time, elapsed time, approval wait and output size. A generous limit does not make an unavailable execution feature available. For a model policy, call `listAgentModels` to discover eligible models and their limits, then `resolveModelPolicy` to pin the selected set's capability revision. Resolution does not call a model or spend inference credits. Published tool and policy references also require exact versions and integrity hashes. ## Build a definition in the platform The Agents page can prepare instructions and schemas without writing application code. Use the schema builder for nested fields, types, required values, choices and bounds. A schema that the builder cannot represent stays available in the JSON editor without being simplified. Store each draft, review its exact content and approve it before publishing the agent version. Uploading freezes that draft; editing the definition creates another immutable version. Selecting tools, policies, collections and a model policy still requires the current published references and your account's permissions. ## Let the agent read its content A run reads the instructions, schemas and knowledge collections its version pins with the agent's own access, and each document in a collection as well. `enableContentAccess` / `enable_content_access` shares all of them with the agent's service account, the documents the collections hold now included, and issues one grant with `synapse:memory:read` naming exactly those, on the budget and expiry you choose. It also names the approved facts of the organization and of the agent, and the documents they cite. When the version lists collections or there are such facts, the grant also allows `synapse:memory:index`, and each collection is shared with the agent as a writer, because a run [indexes its collections and places its facts in the graph when it starts](https://docs.katara.com/products/knowledge.txt#indexing-when-a-run-starts). Content the agent can already read is left as it is, and a request the grant would refuse shares nothing. It takes an owner or admin who manages that content and pays for the budget. A document added to a collection later needs another call. When the selected version pins content the agent cannot read, the platform's Run page offers **Let the Agent Read and Index Its Content**. Select the returned grant in the run's `workload_grants` with audience `katara:synapse`. ## Choose Test behavior explicitly | Run usage | Environment | Behavior and spending | | --- | --- | --- | | `simulation` | Test | Pinned synthetic scenarios; no paid model call or real tool side effect | | `test_compute` | Test | Real metered model calls, retrieval and ingestion where enabled; requires explicit paid-test consent and a funded budget: Account Credits, or test USDC from a wallet or by x402. Policy refuses tool, code and browser effects | | `live` | Live | Real metered execution against admitted live authority and budgets | Use `listSimulationFixtures` in Test and copy the selected entry's complete `model_policy`. Do not invent a fixture name or revision. The catalog includes controlled success, denial and uncertain-execution scenarios; it is not an arbitrary model sandbox. A Test environment's wallet payments settle on the Test network, in test USDC ([Networks](https://docs.katara.com/about/networks.txt)). That includes Test Compute on a budget paid from a wallet or by x402. Test Compute on a credit budget is paid in Account Credits and costs real money. Simulation needs no settlement at all. Any tool touching a chain must use the endpoint and policy explicitly configured for that environment. ## Start a run Prepare an approved JSON input of at most 1 MiB that matches the published input schema. Select the current output store, store version and key version, plus retention between 60 seconds and one year. Pass these with the pinned agent version, grant, budget and usage class to `createRun`. The run reads its input with the access of whoever started it, person or key, so the agent needs no share or grant for it. That run and the runs it starts get it, and only while its starter can still read it. The run can read the input and search or recall with it; adding it to a collection's index still takes the agent's own share and grant. A schedule, or an event source with a `fixed` input, counts as started by the person who enabled it: they chose the input, so its runs read it as that person. A run started by an evaluation, or for an input a signed event names, reads its input with the agent's own access, and so does a run started by another run for the input that run hands it. The platform's Run page loads the selected version's exact input schema into a guided form. Unsupported schema features use an explicit JSON editor. Preparing the values does not start a run: store the input, review and approve it, then review the run's authority, budget, output target and Test or Live behavior before admission. Set `workload_grants` explicitly: one to eight `{id, audience}` references selected for this run. Include the admission `grant_id` with audience `katara:synapse`; add the exact `katara:locus` grants needed for content, tools or other governed operations. All selected grants must belong to the admitted agent and budget, and the caller must be allowed to select their permissions and resources. The worker receives this recorded set; it does not discover additional grants. Revoking or narrowing authority can stop later work. For simulation, use `usage_class: "simulation"` and omit `paid_test_consent_id`. For paid Test Compute, use `usage_class: "test_compute"` with the specific consent ID. Changing a usage class does not convert a simulation definition into a paid model definition. Publish and select the appropriate model policy first. The response's `resource_id` is the admitted run ID. `completed: true` refers to the admission operation; the run itself can still be queued. Save its ID and inspect it with `getRun`. | Status | Meaning for the caller | | --- | --- | | `queued`, `starting` | Accepted and awaiting or entering execution | | `running` | Execution is active | | `waiting` | Inspect the snapshot's wait kind; it may need approval or a delay | | `completed` | Execution completed; inspect its output reference | | `failed`, `cancelled` | Terminal outcome; inspect the reason and any cancellation record | | `reconciliation_required` | An outcome is uncertain; do not repeat the external action | A tool's output is screened by the same detectors that check an action's arguments before the run stores it or shows it to the model. Output both detectors clear passes on unchanged. Output either detector blocks ends the run `failed` with reason `output_blocked`. Output a detector marks for review, or that could not be screened, including output over 64 KiB, ends it `reconciliation_required` with reason `output_held`. In both cases the tool ran and its output is withheld whole: nothing of it is stored, shown or rewritten, and the run's trace carries only the outcome. A run on a budget paid per run with x402 is started with a payment; see [pay for an agent run](https://docs.katara.com/developers/x402.txt#pay-for-an-agent-run). It stops with `time_limit` before its authorization runs out. A run that ends `failed` with reason `insufficient_funds` was stopped because a collection from the wallet paying for it failed. Its work, results and charges are kept. Add USDC to the wallet or raise its allowance; the collection is tried again, and runs on that wallet start again once it is paid. See [when a collection fails](https://docs.katara.com/products/wallet-budgets.txt#when-a-collection-fails). A run that ends `failed` with reason `cannot_complete` had a valid plan: the model concluded that no step the agent may take could complete the request, and stopped. Look at what the agent was given to work with: its instructions, tools and knowledge collections. When a request can rightly have no answer, as when a search finds nothing, let the output schema accept a not-found answer and tell the model in the instructions to complete with it. `invalid_plan` is different: a proposal or decision failed validation, for example a result that does not match the output schema. The SDK does not keep polling or retrying in the background. Choose a polling interval in your application. To cancel, fetch the run's admission digest and pass it to `cancelRun`. Cancellation delivery has its own state; requesting it is not the same as observing a cancelled run. ## Inspect a run trace Expand a run's trace in the platform, or call `getRunTrace(scope, runID)` in TypeScript and `get_run_trace(org_id, environment_id, run_id)` in Python. Results contain bounded metadata and a cursor for the next page. The service checks your current access to the run on every request; an old trace ID does not preserve revoked access. Trace sources cover terminal runs, recorded inference and retrieval outcomes, frozen policy decisions and managed tool outcomes. Each record includes the exact run, environment mode, usage class and reset generation, plus immutable event metadata and its integrity hash. Customer instructions, inputs, outputs and raw errors are excluded. An empty page can mean that no supported event has been recorded yet. A policy event with `waiting` and `approval_required` records the gate at the time it was evaluated. Later approval does not rewrite that historical event; inspect the current action to see whether a decision is still needed. A wait is distinct from denial. An accounting reference identifies the corresponding accounting record; its presence alone does not prove a charge or payment settlement. Model token counts come from finalized usage. An implementation reference can identify the admitted agent definition and must not be relabeled as a model version. Projection delivery is separate from execution. `pending` means the metadata awaits acknowledgement, `delivered` means the trace service acknowledged the verified projection, and `unavailable` means that projection cannot currently be delivered. These states do not change the run's canonical outcome or establish the health of its execution engine. Refresh explicitly to load later records; neither SDK polls or retries automatically. ## Check trace retention The run page shows retention separately from delivery. Use `getRunTraceRetention` in TypeScript or `get_run_trace_retention` in Python to read the same status. Each response belongs to one organization, environment, run and reset generation. | State | Meaning | | --- | --- | | `unconfigured` | No retention policy is recorded for this run; no deadline is assumed | | `active` | The trace service deadline has not passed | | `blocked` | Source authority was withdrawn, an administrator blocked the trace, or the environment was reset | | `expired` | The trace service deadline has passed | Configured responses identify the original policy version and two effective deadlines. Later policy changes can shorten these deadlines but cannot extend them. The response `version` advances when the effective deadlines or access state change. Use the returned deadlines: `projection_expires_at` for the trace service and `metadata_expires_at` for the recorded events returned by the run API. The metadata deadline can be later, so an expired service trace can still have readable recorded events. Check `metadata_state` before treating an empty page as a lack of activity. The platform clears events when access is blocked or their metadata deadline passes. Physical deletion is a separate operation; an expired or blocked status does not confirm that deletion has finished. These policies do not alter result-file retention, charges or payment records. ## Export recorded events The run page can download an immutable snapshot of recorded trace metadata. Choose an export availability period, then select **Download Trace Export**. Katara checks current access before every page; the platform verifies each event hash and the complete manifest before downloading the file. The file excludes prompts, result bodies and raw errors. A downloaded copy stays on your device after its Katara availability expires. API clients need both `synapse:runs:read` and `synapse:runs:export`. Exporting is available to the run's original requester with current reader access. Workload credentials cannot export. A run must have configured, available recorded-event retention and at least one event. Read the current retention status and pass its effective `version` as `expected_retention_version`. Choose `expires_in_seconds` from 60 through 86,400; the entire period must fit inside `metadata_expires_at`. The service rejects a longer period instead of changing your request. A changed retention version needs a new review of the current status. | Operation | TypeScript | Python | | --- | --- | --- | | Create the snapshot | `createRunTraceExport` | `create_run_trace_export` | | Read its manifest | `getRunTraceExport` | `get_run_trace_export` | | Read ordered records | `getRunTraceExportPage` | `get_run_trace_export_page` | | Verify the complete file | `verifyRunTraceExport` | `verify_run_trace_export` | Create with an explicit idempotency key and preserve the same key and body after an uncertain response. A repeat reads the original snapshot; it does not create a new snapshot or extend its deadline. The manifest identifies its exact run, environment, reset generation, lifetime, retention version, record count and integrity hash. Snapshots contain at most 10,000 events, with up to 100 per page. Pass the original manifest to each SDK page read. Start `after` at zero, then use `next_cursor` until it is absent. Collect the ordered `data` items with that manifest and verify `{ manifest, data }`. The TypeScript verifier is exported from `@katara/platform/products`; the Python verifier is in `katara_platform.product_traces`. Verification recomputes both the event and manifest hashes and rejects missing, repeated or changed records. It does not establish payment settlement or the outcome of a later action. Every read rechecks source authority, scope, reset, API key and retention. Losing access to any snapshot source makes the snapshot unavailable; an earlier downloaded page does not preserve that access. The platform rechecks the manifest after local verification before offering its file. For a newer snapshot, refresh Trace and start a new export explicitly. ## Read artifacts `listRunArtifacts` returns metadata for generated requests, planning input, tool arguments, tool results, model replies and candidate results. Artifacts carry source and parent references and remain marked `untrusted`. A candidate result is not by itself a completed run's accepted output. Read a ready artifact with `readRunArtifact`, supplying its exact `content` reference. The SDK checks response headers, byte count and SHA-256 before returning bytes. Current source authority, parent availability, blocking and retention are checked by the service. A reference in an old run does not guarantee that its bytes remain readable. Use `blockRunArtifact` with the artifact digest to withdraw access. Expiry and cleanup are separate states; a blocked or expired record can still show cleanup pending. Follow the verified output reference on the completed run when displaying its final answer. ## Follow a run's sandboxes Code and browser steps run in sandboxes the run keeps for its whole life. `listRunSandboxEvents` / `list_run_sandbox_events` returns what happened to them, in the order it happened: a sandbox created or resumed, a command started and finished with its exit code and duration, a checkpoint taken, the sandbox suspended while the run waited or brought back from its checkpoint after a lost worker, and the sandbox deleted once the run ended. Each event names the sandbox, the step and, for a checkpoint, the checkpoint. None carries a command, its output or a file. Pages hold up to 100 events; pass `next_cursor` as `after` until it is absent. Reading the journal needs run read access, and events are kept for thirty days. A run from before an environment reset reads as not found. ## See what a run has spent `runCharges` / `run_charges` returns what a run has spent and what it still holds, in credits, with the most it may spend. Spent is what the run's own reservations charged: each step's, its model calls, recalls and ingestions. Held includes a reservation awaiting reconciliation. A child run spends from its own allocation, so that is its maximum; any other run's maximum is its budget's limit, which the budget's other runs share, and `maximum_scope` says which. Reading the charges needs both run and billing read access, and the run's page in the portal shows them to people who have both. ## Inspect recovery without creating another run A worker restart can continue the existing workflow with the same admitted run ID. Keep inspecting that ID. A delayed response or a worker restart does not justify submitting a new run or repeating a tool action. A persisted successful result can be recovered without dispatching its effect again. If admission itself returned no response, repeat the identical admission body with the original idempotency key to retrieve its committed identity. Once you have the run ID, use reads to follow it. A later admission with a different key creates a separate operation and can incur more charges. `reconciliation_required` means the outcome still needs resolution. There is no force-retry. The owner or an admin records what they found through the [reconciliation operation](https://docs.katara.com/products/closing-an-organization.txt#resolve-a-run-awaiting-reconciliation): the effect completed, it did not, it was put right by hand, or the cancellation is final. The record is written once and does not charge, refund or retry anything. Until then, display the recorded state and preserve the run ID; do not label an unknown external effect as failed, refunded or safe to repeat. A resolved run keeps the status `reconciliation_required`, because that is how it ended. From the moment the resolution is recorded, the run, as `getRun` / `get_run` and the run list return it, carries a `reconciliation` object with the `outcome` and `recorded_at`, and a run without one is still outstanding. Anyone who reads the run sees those two fields. Who resolved it, the evidence reference and the note stay in the run's reconciliation record. Worker recovery does not guarantee resolution of every uncertain provider or tool outcome. The [SDK recipes](https://docs.katara.com/products/sdks.txt) demonstrate Test admission, a human approval decision, verified final output and inspection during paid recovery. These request and response examples are checked against the API contract in both SDKs. Contract checks do not establish hosted availability or acceptance of a particular paid provider.