> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prysm1.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents

> Run a goal as a cost-bounded, proof-bound multi-step agent. AgentGuard makes runaway spend impossible by construction; every step is bound into a verifiable PrysmProof trajectory.

<Note>
  **POST** `https://api.prysm1.com/v1/agent/run` · Requires authentication
</Note>

Where [`/v1/chat/completions`](/api-reference/chat-completions) routes one prompt to one model
and [`/v2/orchestrate`](/api-reference/orchestrate) crosses several models for one robust
answer, the **agent** endpoints execute a *goal* as a bounded, multi-step trajectory — planning,
crossing models, and finishing on their own.

Two guarantees set PRYSM agents apart, both enforced server-side and verifiable:

* **A hard cost ceiling.** A run with cap `$C` **never spends more than `$C`** — not "+5%", at
  most `$C`. Before each step, [AgentGuard](/concepts/agentguard) bounds the step's worst-case
  cost and only runs it if it fits the remaining budget, downshifting intensity
  (Laser → Halo → Foton) under pressure instead of overspending. Hyper-frontier models are
  ring-fenced out of flat-tier agents by construction.
* **A tamper-evident trajectory.** Every step is hashed into a chain + merkle root — a
  [PrysmProof](/concepts/prysmproof) trajectory. Reorder, drop, or edit any step and verification
  fails. Anyone can verify a trajectory with [`POST /v1/agent/verify`](#verify-a-trajectory) — no
  account required.

***

## Run an agent

<Note>**POST** `/v1/agent/run` · Requires authentication</Note>

### Authorization

<ParamField header="Authorization" type="string" required>
  Your secret key as a bearer token: `Bearer prysm_sk_...`
</ParamField>

### Body

<ParamField body="goal" type="string" required>
  The goal for the agent to accomplish autonomously. (`prompt` is accepted as an alias.)
</ParamField>

<ParamField body="max_cost_usd" type="number">
  The **hard** spend ceiling for the entire run, in USD. The run can never exceed it. Defaults
  to **5× the plan's per-query envelope**. A request above your tier's limit is rejected with
  `402` before any model runs.
</ParamField>

<ParamField body="max_cost_per_step" type="number">
  Optional hard cap for a *single* step (clamped to ≤ the run cap). Useful to keep a
  high-fan-out agent from spending most of its budget on one step. AgentGuard binds it when
  planning each step.
</ParamField>

<ParamField body="max_steps" type="integer" default="50">
  Maximum number of steps before the run stops gracefully. Hard ceiling: `1000`.
</ParamField>

<ParamField body="policy" type="string" default="balanced">
  The objective dial: `efficiency`, `balanced`, or `depth`. Sets the starting intensity; the
  guard still downshifts under budget pressure.
</ParamField>

<ParamField body="idempotency_key" type="string">
  A retry-safe key. A second `/v1/agent/run` with the same key (same user) returns the original
  run **without spending again** — no double-charge.
</ParamField>

<ParamField body="max_tokens" type="integer" default="1024">
  Maximum tokens per underlying model call.
</ParamField>

<ParamField body="temperature" type="number" default="0.5">
  Sampling temperature passed to the underlying models.
</ParamField>

### Response

<ResponseField name="object" type="string">Always `agent.run`.</ResponseField>
<ResponseField name="run_id" type="string">Unique run id, e.g. `agt_9f8e...`. Use it with the other agent endpoints.</ResponseField>
<ResponseField name="status" type="string">`complete`, `budget_exhausted`, or `max_steps_reached`. The run never errors out from budget pressure — it stops gracefully and returns the best partial result.</ResponseField>
<ResponseField name="policy" type="string">The policy the run used.</ResponseField>
<ResponseField name="strategy" type="string">The primary per-step strategy.</ResponseField>
<ResponseField name="plan" type="string[]">The sub-tasks the goal was decomposed into.</ResponseField>
<ResponseField name="steps_taken" type="integer">How many steps executed.</ResponseField>
<ResponseField name="cost_consumed_usd" type="number">Total spend — always ≤ `max_cost_usd`.</ResponseField>
<ResponseField name="max_cost_usd" type="number">The hard cap that was enforced.</ResponseField>
<ResponseField name="remaining_usd" type="number">Budget left.</ResponseField>
<ResponseField name="trajectory_proof" type="string">The run's PrysmProof trajectory root, e.g. `sha256:a1b2c3d4e5f6...`.</ResponseField>
<ResponseField name="output" type="string">The consolidated final result.</ResponseField>

<ResponseField name="steps" type="array">
  The per-step trajectory.

  <Expandable title="steps[]">
    <ResponseField name="index" type="integer">Step index (chain order).</ResponseField>
    <ResponseField name="role" type="string">`subtask` or `finalize`.</ResponseField>
    <ResponseField name="model" type="string">The model that ran the step.</ResponseField>
    <ResponseField name="intensity" type="string">`Laser`, `Halo`, or `Foton` — the rung AgentGuard chose under budget pressure.</ResponseField>
    <ResponseField name="strategy" type="string">The step's orchestration shape.</ResponseField>
    <ResponseField name="cost_usd" type="number">The step's cost.</ResponseField>
    <ResponseField name="confidence" type="number">Confidence in the step, `0`–`1`.</ResponseField>
    <ResponseField name="input_hash" type="string">`sha256:` of the step input (privacy-preserving — never the raw text).</ResponseField>
    <ResponseField name="output_hash" type="string">`sha256:` of the step output.</ResponseField>
    <ResponseField name="step_proof" type="string">The chained per-step proof.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="alerts" type="array">Budget-pressure alerts (70% → WARNING/Halo, 90% → CRITICAL/Foton).</ResponseField>
<ResponseField name="budget" type="object">Plan envelope, tier limit, multiplier, and the enforced cap.</ResponseField>
<ResponseField name="final_message" type="string">Set when a run stopped on budget/steps, e.g. "agent stopped after 7 steps (budget\_exhausted); $4.98 of $5.00 spent."</ResponseField>

***

## List runs

<Note>**GET** `/v1/agent/runs?limit=50` · Requires authentication</Note>

Returns your agent runs, newest first (lightweight — no per-step trajectory). `limit` is
capped at `200`.

<ResponseField name="object" type="string">Always `list`.</ResponseField>
<ResponseField name="count" type="integer">Number of runs returned.</ResponseField>
<ResponseField name="data" type="array">Run summaries (same shape as the run state, plus a truncated `goal`).</ResponseField>

## Get run state

<Note>**GET** `/v1/agent/{run_id}` · Requires authentication</Note>

Lightweight state for polling — `status`, `cost_consumed_usd`, `steps_taken`,
`trajectory_proof`, `output`. Returns `404` if the run isn't yours.

## Get the full trajectory

<Note>**GET** `/v1/agent/{run_id}/trajectory` · Requires authentication</Note>

The full step-by-step audit log **plus a server-side re-verification** of the stored proof.

<ParamField query="full" type="boolean" default="false">
  When `true`, returns the **full 64-hex** per-step hashes and step proofs (instead of the
  truncated display form) **plus a ready-to-POST `verify_request` bundle** — pipe it straight
  into [`POST /v1/agent/verify`](#verify-a-trajectory) to independently re-confirm the run
  without trusting this server. This closes the external-verification loop end-to-end.
</ParamField>

<ResponseField name="steps" type="array">Every step with its hashes, cost, intensity, and per-step proof (full 64-hex when `?full=true`).</ResponseField>

<ResponseField name="verification" type="object">
  Deterministic-replay result: `{ "valid": true, "recomputed_proof": "sha256:...", "n_steps": N, "mismatched_steps": [] }`.
</ResponseField>

<ResponseField name="verify_request" type="object">
  Present only with `?full=true`: a self-contained bundle (`run_id`, `trajectory_proof`,
  `policy`, `strategy`, `output_hash`, `steps`, `step_proofs`) that POSTs directly to
  `/v1/agent/verify` and returns `valid: true`.
</ResponseField>

## Cancel a run

<Note>**POST** `/v1/agent/{run_id}/cancel` · Requires authentication</Note>

V1 runs execute synchronously, so by the time a cancel arrives the run is already terminal —
the endpoint returns its final state and partial result (idempotent), rather than pretending to
interrupt it.

***

## Verify a trajectory

<Note>**POST** `/v1/agent/verify` · **Public — no authentication**</Note>

Independently verify a self-contained trajectory bundle by deterministic replay: recompute each
step proof, the chain of custody, the merkle root, and the trajectory root, then check it matches
the claimed `trajectory_proof`. Lets an external auditor confirm a PRYSM agent's trajectory
**without trusting (or even reaching) PRYSM's servers**. Verification needs the full (64-hex)
per-step hashes. Capped at 2,000 steps.

<ParamField body="run_id" type="string" required>The run id the proof was computed over.</ParamField>
<ParamField body="trajectory_proof" type="string" required>The claimed `sha256:...` root to check.</ParamField>
<ParamField body="steps" type="array" required>The step records (`index`, `model`, `input_hash`, `output_hash`, `cost_usd`, `confidence`, `timestamp`).</ParamField>
<ParamField body="policy" type="string" default="balanced">The run's policy.</ParamField>
<ParamField body="strategy" type="string" default="single">The run's primary strategy.</ParamField>
<ParamField body="output" type="string">The raw final output (we hash it). Or supply `output_hash` directly.</ParamField>
<ParamField body="step_proofs" type="string[]">Optional claimed per-step proofs — when supplied, a tamper is localized in `mismatched_steps`.</ParamField>

<ResponseField name="valid" type="boolean">Whether the trajectory verifies.</ResponseField>
<ResponseField name="recomputed_proof" type="string">The proof recomputed from the supplied data.</ResponseField>
<ResponseField name="mismatched_steps" type="integer[]">Indices of steps whose proof didn't match (empty when valid).</ResponseField>

***

## Errors

| Status | `error`                     | Meaning                                                            |
| ------ | --------------------------- | ------------------------------------------------------------------ |
| `400`  | `no_goal`                   | `goal` (or `prompt`) was empty.                                    |
| `401`  | —                           | Missing or invalid API key.                                        |
| `402`  | `budget_exceeds_tier_limit` | `max_cost_usd` exceeds your tier's ceiling (5× the plan envelope). |
| `404`  | `run_not_found`             | No such run, or it isn't yours.                                    |
| `413`  | `request_too_large`         | Request body exceeds the server limit (default 2 MiB).             |
| `502`  | `agent_error`               | The runner raised unexpectedly.                                    |
| `503`  | `no_provider_available`     | No provider API keys are configured on the server.                 |

<RequestExample>
  ```python Python theme={null}
  from prysm import Prysm

  client = Prysm()
  run = client.agent(
      "Research the top 3 AI gateways, compare pricing, and draft a one-page brief.",
      max_cost_usd=1.00,
  )
  print(run["status"], run["cost_consumed_usd"], "/", run["max_cost_usd"])
  print(run["trajectory_proof"])
  ```

  ```bash cURL theme={null}
  curl https://api.prysm1.com/v1/agent/run \
    -H "Authorization: Bearer $PRYSM_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "goal": "Research the top 3 AI gateways, compare pricing, and draft a one-page brief.",
      "max_cost_usd": 1.00,
      "policy": "balanced"
    }'
  ```

  ```bash Verify (public) theme={null}
  curl https://api.prysm1.com/v1/agent/verify \
    -H "Content-Type: application/json" \
    -d '{ "run_id": "agt_...", "trajectory_proof": "sha256:...", "policy": "balanced",
          "strategy": "ensemble_moa", "output": "...", "steps": [ /* full-hash step records */ ] }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 — run theme={null}
  {
    "object": "agent.run",
    "run_id": "agt_9f8e7d6c5b4a39281706f5e4",
    "status": "complete",
    "policy": "balanced",
    "strategy": "ensemble_moa",
    "plan": [
      "Research the top 3 AI gateways",
      "Compare their pricing",
      "Draft a one-page brief"
    ],
    "steps_taken": 4,
    "cost_consumed_usd": 0.0184,
    "max_cost_usd": 1.0,
    "remaining_usd": 0.9816,
    "trajectory_proof": "sha256:a1b2c3d4e5f60718",
    "output": "One-page brief: across the three gateways, the trade-offs cluster around...",
    "steps": [
      {
        "index": 0,
        "role": "subtask",
        "model": "claude-sonnet-4.5",
        "intensity": "Laser",
        "strategy": "ensemble_moa",
        "cost_usd": 0.0061,
        "confidence": 0.86,
        "input_hash": "sha256:7c1f...",
        "output_hash": "sha256:9b2a...",
        "step_proof": "sha256:1d4e..."
      }
    ],
    "alerts": [],
    "budget": { "plan": "pro", "plan_envelope_usd": 1.0, "tier_limit_usd": 5.0, "max_cost_usd": 1.0, "multiplier": 5 }
  }
  ```

  ```json 402 — over tier theme={null}
  {
    "error": "budget_exceeds_tier_limit",
    "message": "budget_exceeds_tier_limit: requested $50.00 exceeds tier limit $5.00 (plan envelope $1.00 x 5). Reduce max_cost_usd or upgrade plan.",
    "tier_limit_usd": 5.0,
    "plan_envelope_usd": 1.0,
    "requested_max_cost_usd": 50.0
  }
  ```
</ResponseExample>
