# Build an Agent with the SDK

> Define script or durable Agent behavior, call models, read history, and return replay-safe results.

## Before you begin {#before-you-begin}

Create an SDK project and bind a Model under the logical name `model`. Start with script mode; choose durable mode only when explicit resumable state improves the workflow.

## Steps {#steps}

1. Export a validated Agent definition:

   ```ts src/index.ts
   import { agent, type HistoryView } from "@constal/sdk";

   export default agent({
     id: "support-agent",
     version: "1.0.0",
     model: "model",
     async onMessage(message, ctx) {
       const history = await ctx.ledger.view<HistoryView>("history");
       const turn = await ctx.turn({
         system: "Resolve the support request accurately.",
         objective: message,
         context: { previous: history.facts },
         stream: true,
       });
       return { answer: turn.message.content };
     },
   });
   ```

2. Page older history only when the bounded view says more exists:

   ```ts
   const first = await ctx.ledger.view<HistoryView>("history");
   const older = first.more ? await ctx.ledger.page(first.more) : { facts: [], more: null };
   ```

3. Publish an explicit fact when the workflow needs a checkpoint before normal completion:

   ```ts
   if (message.kind === "checkpoint") {
     return ctx.commit({ kind: "checkpoint", payload: message.payload });
   }
   ```

4. Memoize bounded local nondeterminism with a stable step name:

   ```ts
   const normalized = await ctx.step("normalize-v1", async () => normalize(message));
   ```

5. Register every Tool, subtask, view, partition function, fold, and analytics declaration used by the package. Do not accept a model CRN, Resource CRN, or Credential from message input; use the accepted bindings on `ctx`.

## Verify {#verify}

Deploy, start one controlled Run, and inspect the journal. Confirm the Agent revision, Model and Resource snapshot, Policy hash, turn, usage, and committed output. Send the same event id again; it must resolve to the recorded outcome without duplicate work.

## Next steps {#next-steps}

Use [From primitives to production](/docs/foundations/composition.md) to select a composition and [Durable execution](/docs/sdk/durable-execution.md) for waits, tasks, Handles, state machines, and data stages. Use [Resources and Tools](/docs/sdk/resources-and-tools.md) before adding external effects, then [Start a Run](/docs/runs/start.md) to invoke the deployed Agent.
