> ## 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.

# Quickstart

> Create an Agent, start a Session, send a message, and follow its events.

In this quickstart you will create an Agent, start a Session, send
one message, and follow the event stream until the turn settles.

Have a source checkout instead? The [local quickstart](/getting-started/local-quickstart)
needs no hosted key or Docker.

<Note>
  This quickstart uses the simulator. It returns a canned response while exercising
  the real Agent, Session, and event APIs; it does not run the selected harness or model.
  Real managed execution is currently `rollout_fenced`; check the [status page](/getting-started/status) for readiness.
</Note>

<Warning>
  Checkfu is in private alpha. You need an admitted Workspace and API key.
  [Request access](https://checkfu.com/#early-access) if you do not have them.
</Warning>

## Before you start

You need a Workspace-bound API key, a Workspace ID, and a Principal ID. [Get access and create
a Principal](/reference/access) if you do not have all three.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
export CHECKFU_API_KEY="your_api_key"
export CHECKFU_WORKSPACE_ID="wrkspc_0123456789abcdef0123456789abcdef"
export CHECKFU_PRINCIPAL_ID="prin_0123456789abcdef0123456789abcdef"
export CHECKFU_QUICKSTART_ID="$(openssl rand -hex 16)"
```

Keep `CHECKFU_QUICKSTART_ID` unchanged when retrying a request.

<Note>
  Plain HTTP is available to every admitted customer. The CLI and TypeScript SDK
  tabs require private-alpha artifacts or a source checkout. See [CLI
  access](/getting-started/cli-access) and [TypeScript SDK
  access](/reference/typescript-sdk).
</Note>

For the TypeScript tabs, create one client and reuse it:

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

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

## 1. Create an Agent

Creating an Agent automatically creates immutable Version 1. There is no Draft
or publish step.

<CodeGroup>
  ```sh CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  export CHECKFU_AGENT_ID="$(
    checkfu agent create --json --input '{
      "name": "quickstart",
      "model": "claude-opus-5",
      "system": "You are a helpful assistant."
    }' | jq -r '.id'
  )"
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  export CHECKFU_AGENT_ID="$(
    curl --request POST https://api.checkfu.com/v1/agents \
      --header "Authorization: Bearer $CHECKFU_API_KEY" \
      --header "Checkfu-Version: 2026-08-27" \
      --header "checkfu-beta: managed-agents-2026-04-01" \
      --header "Idempotency-Key: quickstart-agent-$CHECKFU_QUICKSTART_ID" \
      --header "Content-Type: application/json" \
      --data '{
        "name": "quickstart",
        "model": "claude-opus-5",
        "system": "You are a helpful assistant."
      }' | jq -r '.id'
  )"
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const agent = await checkfu.beta.agents.create({
    name: "quickstart",
    model: "claude-opus-5",
    system: "You are a helpful assistant.",
  })
  ```
</CodeGroup>

The CLI and cURL tabs set `CHECKFU_AGENT_ID`. TypeScript continues with
`agent.id`. See [Agents](/concepts/agents) for editing, versions, and the full
definition.

## Legacy Session path (temporarily fenced)

<Warning>
  Stop after Agent creation for now. The steps below describe the retired
  Draft/Release/AgentDeployment Session path and are retained only as migration
  context until the CMA-compatible Session slice replaces them. Its commands do
  not work with `checkfu.beta.agents`.
</Warning>

## 2. Deploy the release

A Session admits against an [AgentDeployment](/reference/agent-deployments)
revision, not the Agent directly. Deploying publishes the next immutable
revision of the Workspace's deployment for this Agent, pinning the exact
release plus the harness, model, and sandbox coordinates the Workspace
resolves for it.

<CodeGroup>
  ```sh CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # No CLI command exists for this retired deployment path.
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  export CHECKFU_AGENT_DEPLOYMENT_ID="$(
    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: quickstart-deploy-$CHECKFU_QUICKSTART_ID" \
      --header "Content-Type: application/json" \
      --data '{
        "agent_release_number": 1,
        "target_workspace_id": "'"$CHECKFU_WORKSPACE_ID"'"
      }' | jq -r '.id'
  )"
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const agentDeployment = await checkfu.agents.deploy(agent.id, {
    agent_release_number: 1,
    target_workspace_id: process.env.CHECKFU_WORKSPACE_ID!,
  })
  ```
</CodeGroup>

Deploying the same release again converges on the same deployment head. It
never copies the Agent or forks its identity. Multiple deployments of one
Agent (a `stable` and a `canary` key) are how you vary execution per Session
now; there is no per-Session override knob.

## 3. Start a Session

A Session is the durable conversation. It runs as a Principal and can contain
many short-lived Runs. It admits against the deployment's current revision;
omitting `agent_deployment_revision_number` resolves that revision once, and
providing it pins one exact revision.

<CodeGroup>
  ```sh CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  export CHECKFU_SESSION_ID="$(
    checkfu session create \
      --agent-deployment "$CHECKFU_AGENT_DEPLOYMENT_ID" \
      --principal "$CHECKFU_PRINCIPAL_ID"
  )"
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  export CHECKFU_SESSION_ID="$(
    curl --request POST \
      "https://api.checkfu.com/v1/sessions" \
      --header "Authorization: Bearer $CHECKFU_API_KEY" \
      --header "Checkfu-Version: 2026-08-27" \
      --header "Idempotency-Key: quickstart-create-$CHECKFU_QUICKSTART_ID" \
      --header "Content-Type: application/json" \
      --data '{
        "agent_deployment_id": "'"$CHECKFU_AGENT_DEPLOYMENT_ID"'",
        "principal": "'"$CHECKFU_PRINCIPAL_ID"'"
      }' | jq -r '.id'
  )"
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const session = await checkfu.sessions.create({
    agent_deployment_id: agentDeployment.id,
    principal: process.env.CHECKFU_PRINCIPAL_ID!,
  })
  ```
</CodeGroup>

The CLI and cURL tabs set `CHECKFU_SESSION_ID`. TypeScript continues with
`session.id`.

<Accordion title="Selected response fields">
  ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "id": "sess_0123456789abcdef0123456789abcdef",
    "status": "pending",
    "agent_id": "agent_0123456789abcdef0123456789abcdef",
    "agent_deployment_id": "adep_0123456789abcdef0123456789abcdef",
    "agent_deployment_revision_number": 1,
    "agent_release_number": 1,
    "release_hash": "sha256:9f2c1a4b7d3e5f6081920a3b4c5d6e7f8091a2b3c4d5e6f70819a2b3c4d5e6f7"
  }
  ```

  `agent_deployment_id` and `agent_deployment_revision_number` identify the
  immutable deployment revision the Session admitted; `agent_id` and
  `agent_release_number` name the Agent release that revision pins.
</Accordion>

## 4. Send a message

Every human-authored event names the Principal who wrote it and its cause.

<CodeGroup>
  ```sh CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  checkfu session steer "$CHECKFU_SESSION_ID" \
    "Hello from the Checkfu quickstart." \
    --principal "$CHECKFU_PRINCIPAL_ID"
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST \
    "https://api.checkfu.com/v1/sessions/$CHECKFU_SESSION_ID/events" \
    --header "Authorization: Bearer $CHECKFU_API_KEY" \
    --header "Checkfu-Version: 2026-08-27" \
    --header "Idempotency-Key: quickstart-message-$CHECKFU_QUICKSTART_ID" \
    --header "Content-Type: application/json" \
    --data '{
      "type": "user.message",
      "payload": {
        "content": "Hello from the Checkfu quickstart.",
        "authored_by": "'"$CHECKFU_PRINCIPAL_ID"'",
        "caused_by": {
          "kind": "api"
        }
      }
    }'
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  await checkfu.sessions.events.send(session.id, {
    type: "user.message",
    payload: {
      content: "Hello from the Checkfu quickstart.",
      authored_by: process.env.CHECKFU_PRINCIPAL_ID!,
      caused_by: { kind: "api" },
    },
  })
  ```
</CodeGroup>

The simulator replies with a canned `agent.message`. The durable admission,
ordered events, and settlement are real; no harness or model runs in this
tutorial.

## 5. Follow the event stream

<CodeGroup>
  ```sh CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  checkfu session follow "$CHECKFU_SESSION_ID" --until-boundary
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --no-buffer \
    "https://api.checkfu.com/v1/sessions/$CHECKFU_SESSION_ID/events/stream" \
    --header "Authorization: Bearer $CHECKFU_API_KEY" \
    --header "Checkfu-Version: 2026-08-27"
  ```

  ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const turnBoundaries = new Set([
    "session.status_idle",
    "session.status_completed",
    "session.status_failed",
    "session.status_canceled",
  ])

  for await (const event of checkfu.sessions.events.stream(session.id)) {
    console.log(event.seq, event.type)
    if (turnBoundaries.has(event.type)) break
  }
  ```
</CodeGroup>

The stream first replays persisted events, then stays open for new ones. A turn is settled only when the log contains `session.status_idle`, `session.status_completed`, `session.status_failed`, or `session.status_canceled`.

The CLI and TypeScript tabs stop at the boundary. cURL stays connected; press
<kbd>Ctrl</kbd>+<kbd>C</kbd> after a boundary event appears.

<Accordion title="Read events without a live stream">
  Use the paged event log when you only need persisted history.

  <CodeGroup>
    ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl --request GET \
      "https://api.checkfu.com/v1/sessions/$CHECKFU_SESSION_ID/events?limit=2" \
      --header "Authorization: Bearer $CHECKFU_API_KEY" \
      --header "Checkfu-Version: 2026-08-27"
    ```

    ```ts TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const events = await checkfu.sessions.events.list(session.id, {
      limit: 2,
    })
    ```
  </CodeGroup>
</Accordion>

You now have a published Agent and a durable Session you can continue driving.

## If a request fails

* `401 auth.invalid_key`: check the bearer token and its scope.
* `400 validation.malformed`: check `Checkfu-Version` and the request schema.
* `404 validation.not_found`: confirm the resource ID belongs to the key's Workspace.
* `409 validation.conflict`: re-read the Agent and use its current top-level
  `version` as `expected_version`.

Switch on `error.type`, not the human-readable message. The [error
reference](/reference/errors) lists every stable type.

## Next steps

<CardGroup cols={2}>
  <Card title="Add Checkfu to an app" href="/guides/add-an-agent-to-your-app">
    Keep driving the same Session with the TypeScript SDK or plain HTTP.
  </Card>

  <Card title="Understand Sessions" href="/concepts/sessions-and-runs">
    Learn how durable Sessions, short-lived Runs, and ordered events fit together.
  </Card>

  <Card title="Use tools" href="/concepts/tools">
    Choose built-in, connected, or application-executed tools.
  </Card>

  <Card title="Run locally" href="/getting-started/local-quickstart">
    Complete a durable turn from a Checkfu source checkout.
  </Card>
</CardGroup>
