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

# TypeScript SDK

> The generated @checkfu/sdk client for canonical Checkfu resources, Sessions, AutomationGraphs, and Custom-tool serving.

`@checkfu/sdk` is a typed client for the public Checkfu API. Its resource surface is generated from the reviewed OpenAPI contract. The hand-written core supplies transport, retries, idempotency, pagination, event streaming, projections, and Custom-tool serving.

The SDK is an interface over the public contract. It is not a second product model or mutation authority.

<Note>
  The import and method names below match the current generated output in the repository.
</Note>

<Warning>
  The Checkfu CLI and TypeScript SDK are private-alpha artifacts with no self-service public installation channel.
  Part of this flow is behind a rollout fence; a deployment that has not enabled it refuses the request rather than running it.
  Confirm [capability status](/getting-started/status) before making availability part of your application's contract.
</Warning>

## Create a 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,
})
```

The API key is bound to one Workspace. Do not add a per-call Workspace selector to generated methods.

Client configuration:

* `apiKey` falls back to `CHECKFU_API_KEY`.
* `baseUrl` takes precedence over `CHECKFU_BASE_URL`, then `CHECKFU_API_URL`, then the default `https://api.checkfu.com`. Only the `CHECKFU_API_URL` fallback removes a trailing `/v1`, since SDK request paths already include it.
* `timeout` defaults to 60,000 ms; `maxRetries` defaults to 2. Invalid values fail at client construction.
* `fetch` lets you supply a transport for tests or another runtime.

## Use generated request types

Use the operation helpers when an example would otherwise duplicate a request schema:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import type { BodyOf, Op, ResultOf } from "@checkfu/sdk"

type CreateAgentInput = BodyOf<Op<"agents.createAgent">>
type Agent = ResultOf<Op<"agents.getAgent">>
```

`BodyOf`, `PathOf`, `QueryOf`, and `ResultOf` derive directly from an `Op`. They are safer than a hand-maintained interface and make generated drift visible at compile time.

## Agent methods

The generated Agent surface lives under `checkfu.agents`:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
await checkfu.agents.create(input)
await checkfu.agents.list()
await checkfu.agents.retrieve(agentId)
await checkfu.agents.update(agentId, update)
await checkfu.agents.promote(agentId, promote)
await checkfu.agents.archive(agentId)
await checkfu.agents.versions.list(agentId)
```

`promote` deploys an Agent into a `target_workspace_id` with exact source-version and dependency mappings; derive its body from `BodyOf<Op<"agents.promoteAgent">>`.

Agent is mutable. Every material change creates the next immutable AgentVersion. Use the generated `version` field when the update body exposes optimistic concurrency; do not build a separate draft or release layer around it.

Use these canonical Agent operations from your application or repository CI. Your CI owns merge policy; ordinary Agent mutations require authenticated authorization and concurrency checks.

## Signed Session inputs

A Session can carry an organization-signed review of its exact configuration and input
material in `material_review`. Source or build review alone does not certify future
Session input. Signing does not grant execution: admission still checks current signer
policy, permissions, placement and workload restrictions.

Register the Ed25519 public key through `checkfu.workloadReviewPolicies.publish` using
an administrative API key. Keep the private key in your signing system. Retrieve the
selected immutable Agent Version, Environment, HarnessProfile Version and Release
before preparing a review.

Use the exported helpers to avoid reproducing canonical JSON and hash prefixes:

| Helper | Input it commits or prepares |
| - | - |
| `agentWorkloadBuildReviewStatement` | Exact Profile Version and source-backed OCI Release; its `binding.input_manifest_digest` is the Session's `build_material_digest` |
| `sessionWorkloadReviewAgent` | The selected Agent Version |
| `sessionResourceMaterialDigest` | Reviewed, credential-free resource provenance |
| `sessionMemoryPromptDigest` | Resolved Memory bindings, including effective access, instructions and destination |
| `sessionInitialInputDigest` | One normalized initial message or outcome, using `{ type, payload }` |
| `sessionIngressPolicyDigest` | The explicit policy for later direct API-key writers |
| `sessionInputManifestDigest` | Ordered initial-input commitments, staged files, resource and Memory digests, and ingress policy digest |
| `sessionWorkloadReviewStatement` | The Session configuration, build digest and input-manifest digest |
| `workloadReviewSigningText` | The exact UTF-8 statement text to sign with Ed25519 |

The helpers validate and hash supplied material; they do not fetch files, resolve URLs
or review content for you. Initial-input hashing requires resolved inline content.
Memory rendering is shared with the server. The server independently resolves and
checks material before accepting the signature, so a changed source or configuration
is refused.

Send the signed statement, key ID and base64url signature in
`material_review.review`, with the reviewed `material_review.ingress_policy`. Pin the
Agent selector with `{ type: "agent", id, version }`. An empty `api_key_ids` list
treats only the reviewed initial input as controlled. Later input must satisfy this
policy when native activation revalidates the review. Named writers must still pass
ordinary authentication and authorization. Vault attachments are
outside this review's material scope and cannot obtain the trusted exception.

This preparation surface does not change the current [capability status](/getting-started/status)
or qualify a harness or sandbox provider.

## Agent source validation

Validate Agent configuration source before sending it. The call stores nothing:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
checkfu.agentBlueprints.validate(organizationId, body, options?)
```

Derive the request body from `BodyOf<Op<"agentBlueprints.validateSource">>`. Checkfu has no Blueprint package lifecycle in the SDK. Create Agents, Environments, grants, Connections, Automations, and Memory through their own resource methods.

## Create a Runner-based Session

Create or select an Environment, create an Agent, grant it use of that
Environment, then admit a Session with the current direct shape. The example
assumes `claude-code` and the model route are qualified in your Workspace;
substitute the names your Workspace actually serves.

Preflight reports public readiness checks and their remedies. Without an explicit
`runnerPoolId`, an empty Workspace Runner list does not block it: hosted capacity
is checked at Run start. Passing preflight does not guarantee Session admission
or available capacity.
An incomplete Session support-readiness check reports missing prerequisites or
qualifying release evidence. A Workspace can serve a qualified subset while
its broader Session support remains incomplete, for example when that subset
has not proved steering. This diagnostic does not decide admission for the
selected Agent and Environment; a successful basic Session does not promote
Workspace support or prove advanced capabilities.

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

const environment = await checkfu.environments.create({
  name: "sdk-example-environment",
})

const agent = await checkfu.agents.create({
  name: "sdk-example-agent",
  model: "claude-opus-5",
  harness: "claude-code",
  system: "You are a helpful assistant.",
})

await checkfu.permissionAssignments.create(
  agentEnvironmentUseAssignment(agent.id, environment.id),
)

const preflight = await checkfu.preflight({
  agentId: agent.id,
  environmentId: environment.id,
})
const launchBlockers = preflight.blockers.filter(
  (blocker) => blocker.check !== "session_capability",
)
if (launchBlockers.length > 0) {
  throw new Error(launchBlockers.map((blocker) => blocker.remedy).join("\n"))
}
for (const diagnostic of preflight.blockers.filter(
  (blocker) => blocker.check === "session_capability",
)) {
  console.warn(diagnostic.remedy)
}

const session = await checkfu.sessions.create({
  agent: { type: "agent", id: agent.id },
  environment_id: environment.id,
})

const inputEvent = await checkfu.sessions.events.send(session.id, {
  type: "user.message",
  payload: {
    content: "Hello from the SDK.",
    caused_by: { kind: "api" },
  },
})

for await (const event of checkfu.sessions.events.stream(session.id, {
  lastEventId: inputEvent.seq,
})) {
  console.log(event.seq, event.type)
  if (
    event.type === "session.status_idle" ||
    event.type === "session.status_completed" ||
    event.type === "session.status_failed" ||
    event.type === "session.status_canceled"
  ) break
}
```

Session admission freezes one AgentVersion and one Environment. The message
starts a turn; the stream follows events after that accepted input. An idle
boundary with `stop_reason: "requires_action"` needs a tool result or approval
before the turn settles. Updating the Agent later does not rewrite the existing
Session.

`preflight` reads the API's Workspace-specific Session capability status along
with the selected Agent, Environment, and ready pool Runner presence. Its `ready`
value means these public checks found no blocker; it does not certify the exact
HarnessProfile, model route, placement, or permissions. Session creation makes
that final admission decision and may still return a typed refusal for a missing
or mismatched image, missing or expired qualification, or insufficient authority.
The example leaves those server refusals intact; it treats only the broader
`session_capability` result as a diagnostic when attempting an already qualified
subset. Replace the example's harness and model with a qualified combination in
your Workspace.
Connected-runtime turns select `connected_runtime` when driving a user message;
this Runner preflight does not assess that execution route.

Session creation accepts an authorized `acted_as` Principal under the [Session identity rules](/reference/access#session-identity). The authenticated API key supplies Workspace authority, and the server records attribution. The unsupported `principal` and `authored_by` fields are not identity overrides.

## AutomationGraph authoring

`checkfu.automationGraphs` is the generated resource group for revisioned authored composition. Its current methods include:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
create
list
retrieve
update
preview
test
layout.update
versions.list
versions.retrieve
plan
apply
applications.list
applications.retrieve
applications.submitWebhookSecret
drift.retrieve
archive
```

Use generated operation types for plan and apply rather than guessing their bodies:

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

type PlanGraphInput = BodyOf<Op<"automationGraphs.planAutomationGraph">>
type ApplyGraphInput = BodyOf<Op<"automationGraphs.applyAutomationGraph">>

export const planGraph = (graphId: string, input: PlanGraphInput) =>
  checkfu.automationGraphs.plan(graphId, input)

export const applyGraph = (graphId: string, input: ApplyGraphInput) =>
  checkfu.automationGraphs.apply(graphId, input)
```

AutomationGraph plan/apply may create or update canonical resources and hold an application claim. `applications.submitWebhookSecret` is the exact generated method for the human-only, write-only completion of one waiting webhook application; it does not expose or retain the secret. It is not projected as a model-callable MCP operation. AutomationGraph does not fire an Automation, create a second transcript, or execute an Agent. Automation and Session retain those authorities.

## Authoring authority

The SDK invokes canonical resource operations. A request, repository, or local
plan does not reserve a resource. Authentication, authorization, concurrency,
and resource-specific policy remain server-enforced.

Agent create and update are the only configuration writes that produce an
AgentVersion. No SDK method applies a package of resources; create each
resource through its own method. Resolve typed conflicts through the supported
resource workflow. See
[Authoring authority](/concepts/agent-blueprints#authoring-authority).

## Custom tools

`defineTool` declares one customer-executed tool. `checkfu.tools.sync(agentId, tools)` reconciles the Agent's Custom-tool declarations and the ActionPolicies required by `needsActionApproval`. `checkfu.tools.serve(...)` serves calls for explicit Session IDs from your application process.

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

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

const tools = [
  defineTool({
    name: "health_check",
    description: "Return the identity the admitted Run is acting for.",
    schema: {
      type: "object",
      properties: {},
      additionalProperties: false,
    },
    handler: async (_input, context) => ({
      ok: true,
      acted_as: context.actedAs,
    }),
  }),
]

await checkfu.tools.sync(agent.id, tools)
const toolSession = await checkfu.sessions.create({
  agent: { type: "agent", id: agent.id },
  environment_id: environment.id,
})

const controller = new AbortController()
await checkfu.tools.serve({
  sessions: [toolSession.id],
  tools,
  signal: controller.signal,
})
```

Sync tools before creating the Session that will use them. Session creation freezes the current AgentVersion, so syncing the Agent does not add tools to an earlier Session.

Coordinate `tools.sync` with the Agent's configuration workflow. If you also apply the Agent from a checked-in project with `checkfu agent apply`, keep the Custom-tool declarations in that project so the next apply does not remove them. The helper invokes canonical Agent operations and does not grant a separate ownership-transfer authority.

The handler and business credentials remain in your application. Checkfu owns the Session event protocol and ActionApproval authority. The SDK never moves raw provider credentials into an Agent runtime.

## Pagination and events

Generated list methods return a `Page` that is also an async iterable:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
for await (const agent of await checkfu.agents.list()) {
  console.log(agent.id)
}
```

`checkfu.sessions.events.list(sessionId)` reads durable history. `checkfu.sessions.events.stream(sessionId)` tails the same authoritative event log with resume behavior supplied by the SDK core.

## Session exports

`checkfu.sessions.exportBundle(sessionId)` returns a decoded, runtime-validated
Session Bundle. It buffers the response with a 64 MiB ceiling. For a large Bundle,
download its bytes through `exportBundleStream` and pipe them to a writable
destination you own:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
async function downloadBundle(
  sessionId: string,
  destination: WritableStream<Uint8Array>,
  signal?: AbortSignal,
) {
  const stream = await checkfu.sessions.exportBundleStream(sessionId, { signal })
  await stream.pipeTo(destination, { signal })
}
```

The byte stream does not decode or validate the Bundle's JSON. Read it to EOF or
cancel it; the request timeout and caller abort remain active until it closes.
`checkfu.sessions.exportStream` provides the same behavior for the owned-log export.

## Read-side projections

`createSessionProjections()` and the individual projectors (`MessageProjector`, `ToolCallProjector`, `InteractionProjector`, `SubagentProjector`, `ContextLedgerProjector`) fold Session events into process-local read models. They do not own another transcript or durable cursor authority.

## Errors, retries, and idempotency

Non-success responses throw `CheckfuError` subclasses generated from the public error registry. Retry behavior follows the typed retryability contract. Mutating methods that accept idempotency use one stable key across transport retries.

An idempotent transport retry does not make an uncertain external effect safe to repeat. Recovery and Custom-tool handlers must still preserve the platform's uncertainty boundaries.

## Prepare a workload build review

`agentWorkloadReviewStatement` prepares a configuration-only review.
`agentWorkloadBuildReviewStatement` additionally binds an immutable HarnessProfile
Version and its HarnessRelease, including launch configuration and build provenance.
Retrieve them through `checkfu.harnessRuntime.profiles.versionRetrieve(profileId, version)`
and `checkfu.harnessRuntime.releases.retrieve(organizationId, profileVersion.release_id)`.
The build helper requires an OCI release with server-owned source provenance and
matching Workspace and release coordinates. It uses the public responses directly.

Given those retrieved records and an Ed25519 private key held by your review system:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { sign } from "node:crypto"
import { agentWorkloadBuildReviewStatement, workloadReviewSigningText } from "@checkfu/sdk"

const statement = await agentWorkloadBuildReviewStatement(agent, {
  workspaceId,
  profileVersion,
  release,
  issuedAt: new Date().toISOString(),
  expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
})
const signature = sign(
  null,
  Buffer.from(workloadReviewSigningText(statement, keyId)),
  reviewPrivateKey,
).toString("base64url")

await checkfu.agents.update(agent.id, {
  workload_trust: {
    value: "trusted",
    build_review: { statement, key_id: keyId, signature },
  },
})
```

The signer must be registered in the current Workspace review policy, and publication
requires administrative authority. Session admission must resolve the reviewed build;
changing a Profile Version requires a matching new review. A build review does not
review future Session inputs, resources or capability output, and does not enable
trusted execution by itself. The private-alpha rollout restrictions above still apply.

## Generated-surface rule

If a generated method is absent, do not document a convenience method that would make the prose symmetrical. Use the currently generated name or plain HTTP for a served operation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.