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

# Edit agent instructions without a redeploy

> Version, stage, and deploy instruction changes with no engineer and no redeploy — and why those changes never shift underneath a running session.

<Warning>
  This guide is migration-fenced because it describes the retired separate
  Draft, Release, and AgentDeployment lifecycle. With `checkfu.beta.agents`, an
  update automatically creates the next immutable Version. See
  [Agents](/concepts/agents) for the executable contract.
</Warning>

An Agent's instructions are configuration data behind the API, not code in a deployment. A domain expert can change them and the change reaches new sessions with no engineer and no redeploy. What it never does is shift silently underneath a session that is already running.

This page is the model behind both halves of that promise. The mechanics of editing and publishing are in [Agents](/concepts/agents) and the end-to-end [Create and publish an Agent](/guides/create-and-publish-an-agent) guide; this page stays on what makes the workflow safe for a non-engineer to own and why "new sessions only" is a feature rather than a limitation.

`CHECKFU_API_KEY`, `CHECKFU_WORKSPACE_ID`, and `CHECKFU_PRINCIPAL_ID` come from [Get access](/reference/access#the-three-variables-ready); `CHECKFU_AGENT_ID` is the `agent_…` returned when the Agent was created. The TypeScript tabs below use the [TypeScript SDK](/reference/typescript-sdk) with this client:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { Checkfu } from "@checkfu/sdk"

const checkfu = new Checkfu({
  apiKey: process.env.CHECKFU_API_KEY,
})
```

## Instructions are data, not a deploy

A definition is a row. Changing the instructions is an ordinary API write against the draft, and the draft is never what a session runs. There is no image to rebuild, no harness to redeploy, no runner to restart — a definition is not a deploy in the first place.

The [markdown floor](/concepts/agents#a-page-of-markdown-is-an-agent) makes this literal: a single page of markdown is a complete agent, so the thing a domain expert maintains is prose. Editing it is `PATCH /v1/agents/{id}` on the draft; freezing it is `POST /v1/agents/{id}/releases`. Publishing is a separate human act, never a side effect of editing.

Because both steps are ordinary API operations, the surface a domain expert uses is whatever you build on top of them — your own builder UI, or the console's Agents page. The [embed an agent builder](/guides/embed-an-agent-builder) guide covers composing that surface from the public API. Every edit and every publish lands as an ordinary attributed, audited operation, so a change is reviewable after the fact without anyone having staged a pull request.

## Every change is a frozen, numbered version

Checkfu keeps the mutable thing you edit separate from the immutable thing a session runs:

|                      | Draft                         | Published version           |
| -------------------- | ----------------------------- | --------------------------- |
| What it is           | The working copy on the Agent | A numbered, frozen snapshot |
| How it changes       | `PATCH /v1/agents/{id}`       | Never; publish a new one    |
| Can a session run it | No                            | Yes                         |

A domain expert can iterate on the draft as many times as needed. Publishing freezes the current draft as an immutable version — version 1, 2, 3, and so on — and the newest is the Agent's `latest_published_version`. Two concurrency guards keep a publish loop honest: patching with an unchanged body is a no-op rather than a new revision, and publishing a draft identical to the latest published version returns `409 validation.conflict` rather than minting a duplicate. See [the three counters](/concepts/agents) for the distinction between the resource `version`, `draft_revision`, and published version numbers.

## New sessions pick up the change; running sessions do not

This is the central rule. A session resolves its deployment revision once, at admission, and freezes it for the life of that session:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "agent_deployment_id": "adep_…" }
{ "agent_deployment_id": "adep_…", "agent_deployment_revision_number": 3 }
```

Omitting the number resolves the deployment's current revision at admission; providing it selects one exact revision. Either way the resolved choice is recorded on the session as `agent_deployment_revision_number`, `agent_release_number`, and `release_hash`, so what ran is inspectable afterward and cannot change.

So when your domain expert publishes release 4 and the deployment's next revision pins it, sessions admitted after that revision run release 4, and sessions already running keep running whatever they were admitted on. The change is immediate for the next conversation and deliberately absent from the one in flight. This is law 5 — change never lands mid-run — and it is the property the rest of this page depends on.

## Why not propagate edits live: run attribution

The natural question is why a published change does not reach a session already running. The answer is that a run is only meaningful if you can say exactly which instructions it ran under.

Version freeze makes every run attributable to an exact configuration. A session's `agent_deployment_revision_number`, `agent_release_number`, and `release_hash` pin a single point in configuration space, so an [Outcome](/concepts/outcomes) verdict, a usage line, or a trace is evidence about that specific deployment revision — never about a moving target. You can compare revision 3 against revision 4 because each is a frozen, citable thing.

The alternative is a live-propagating context model, where instruction edits flow into sessions that are already running. That is convenient in the moment — a domain expert's edit is visible everywhere immediately — but it breaks attribution: the instructions a run executed under become "whatever the shared context held at that instant," not a version you can name, replay, or compare against. Good for ergonomics, structurally wrong for evaluating, comparing, or improving agents, because a verdict can no longer be tied back to a configuration.

Checkfu takes the version-freeze side of that trade on purpose. The ergonomics a domain expert wants — "my edit takes effect" — are delivered by *new* sessions adopting the deployment's next revision immediately, which they do. The attribution an evaluation needs is delivered by *running* sessions keeping their frozen revision, which they do. Law 5 is what lets a graded verdict be evidence about a specific configuration rather than about a shifting baseline, and it is also what makes the self-improving loop below safe to run.

## Deploy the same release to an explicit Workspace

Deployment publishes an exact-pin revision of the explicitly selected target
Workspace's [AgentDeployment](/reference/agent-deployments) from one already-published
release, without re-authoring it. The request names the target Workspace explicitly;
names or tags such as Development, Staging, and Production never select it:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST \
    "https://api.checkfu.com/v1/agents/$CHECKFU_AGENT_ID/deploy" \
    --header "Authorization: Bearer $CHECKFU_API_KEY" \
    --header "Checkfu-Version: 2026-08-27" \
    --header "Idempotency-Key: deploy-$CHECKFU_AGENT_ID-4" \
    --header "Content-Type: application/json" \
    --data '{ "agent_release_number": 4, "target_workspace_id": "wrkspc_0123456789abcdef0123456789abcdef" }'
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  await checkfu.agents.deploy(agent.id, {
    agent_release_number: 4,
    target_workspace_id: "wrkspc_0123456789abcdef0123456789abcdef",
  })
  ```
</CodeGroup>

The release arrives in the target Workspace unchanged because a definition references its runtime tuple — `harness`, `model_routing_profile_key`, `environment` — by logical name, and each Workspace resolves those names to its own concrete resources. The same vetted release your domain expert approved in one Workspace is the release the target's deployment revision pins, byte-for-byte. Deployment requires an administrator key, and it never copies or forks the Agent: the target's deployment head is deterministic over `(Workspace, Agent)`, and repeating a completed deploy converges on that head. When the target Workspace holds every profile the release names, the published revision pins those exact revisions; otherwise the deploy records the deployment head only, so a missing profile is visible rather than silently defaulted.

This is distinct from the draft-to-published step (`POST /v1/agents/{id}/releases`), which freezes a version inside one Workspace. Deployment carries a published release between Workspaces. See [Deployment between Workspaces](/concepts/agents#deployment-between-workspaces) for the full rule.

## Improve instructions from graded evidence

When the edit a domain expert needs is not a known fix but a lesson drawn from how the agent actually did, Checkfu closes that loop with an **InstructionProposal** — a review workflow, not an autonomous rewrite:

1. Select sessions that carried [Outcomes](/concepts/outcomes). The first supplies the replay task and rubric; failing or needs-revision verdicts are the signal.
2. A reflection job produces span-addressed deltas against the current draft, each citing the verdict evidence that motivated it — never a wholesale rewrite.
3. The proposal is holdout-evaluated before it may touch anything: a baseline session and a candidate session replay the source task and rubric in two isolated graded sessions, and only candidate success where the baseline failed counts as improvement.
4. Applying an evaluated proposal is an ordinary attributed `PATCH` against the draft. Publishing stays a separate human act, and law 5 makes adoption safe — live sessions keep their admitted revision and new sessions pick up the published improvement once the deployment pins it.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # Create a proposal from graded outcome evidence. `source_session_ids`
  # carries 1–8 sessions; the first supplies the replay task and rubric.
  # `model_routing_profile_key` is the reflection route and must differ from the
  # agent's own model routing profile — the judge-collapse guard.
  curl --request POST https://api.checkfu.com/v1/instruction-proposals \
    --header "Authorization: Bearer $CHECKFU_API_KEY" \
    --header "Checkfu-Version: 2026-08-27" \
    --header "Idempotency-Key: proposal-$(uuidgen)" \
    --header "Content-Type: application/json" \
    --data '{
      "agent": "'"$CHECKFU_AGENT_ID"'",
      "source_session_ids": ["'"$CHECKFU_SESSION_ID"'"],
      "model_routing_profile_key": "reflection"
    }'
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const proposal = await checkfu.instructionProposals.create({
    agent: agent.id,
    source_session_ids: [sessionId],
    model_routing_profile_key: "reflection",
  })

  // Evaluate before it may touch the draft. The holdout baseline/candidate
  // Sessions are admitted under the requesting Principal.
  await checkfu.instructionProposals.evaluate(proposal.id, {
    principal: process.env.CHECKFU_PRINCIPAL_ID!,
  })

  // Only an improved, evaluated proposal may apply — to the draft only
  await checkfu.instructionProposals.apply(proposal.id)
  ```
</CodeGroup>

The whole loop rests on the attribution property above: a candidate is a frozen version you can holdout-evaluate precisely because a definition version is a point in configuration space, not a live stream of edits. Put user-specific facts and preferences in [Memory](/concepts/memory), and use the governed [skill-source loop](/concepts/capabilities) when the improvement changes a reusable capability rather than the agent's instructions.

## Observe a publish

Definition-version lifecycle events — a release published, deployed, or created — are **not** in the subscribable webhook catalog today. Outbound [webhooks](/guides/receive-webhooks) are scoped to the session log: session status transitions, `run.*`, `action_approval.*`, and `outcome.evaluation_*`. A publish or deploy is a control-plane write, not a session-log event, so it produces no webhook delivery. The catalog lists no literal before the platform can deliver it, and definition-version lifecycle has no such delivery path today.

To observe a publish today, read the resource:

| What you want                                | How                                                                                                                   |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| The newest published version                 | `GET /v1/agents/{id}` and read `latest_published_version`                                                             |
| The deployment head and its current revision | `GET /v1/agent-deployments/{agent_deployment_id}` and read `current_revision_number`                                  |
| The full version history                     | `GET /v1/agents/{id}/releases`                                                                                        |
| Who changed what, and when                   | `GET /v1/audit?agent_id=…` — every edit, publish, and deploy is an attributed audit record                            |
| Exactly what a version contained             | `GET /v1/agents/{id}/releases/{release_number}`, or `GET /v1/agents/{id}/export?version=N` for the readable directory |

If your integration needs to react the moment a domain expert publishes, poll `latest_published_version` (or the audit ledger) on your own cadence — there is no push to subscribe to today.

## Next steps

<CardGroup cols={2}>
  <Card title="Create and publish an Agent" icon="rocket" href="/guides/create-and-publish-an-agent">
    The end-to-end author, publish, and run flow this page builds on.
  </Card>

  <Card title="Agents" icon="robot" href="/concepts/agents">
    The full definition shape, the lifecycle, and the version counters.
  </Card>

  <Card title="Embed an agent builder" icon="wrench" href="/guides/embed-an-agent-builder">
    Compose the surface a non-engineer edits through, from the public API.
  </Card>

  <Card title="Outcomes" icon="flag-checkered" href="/concepts/outcomes">
    The graded definitions of done that feed instruction proposals.
  </Card>
</CardGroup>
