{
  "uid": "cogitave.learn.build-your-first-agent-with-namzu.build-an-agent",
  "kind": "moduleUnit",
  "href": "/modules/build-your-first-agent-with-namzu/build-an-agent/",
  "title": "Exercise - Your first call, and your first tool",
  "summary": "",
  "type": null,
  "products": [],
  "roles": [],
  "levels": [],
  "subjects": [],
  "headings": [
    "Before you start",
    "1. Install the kernel and one driver",
    "2. Register a provider",
    "3. Send your first call",
    "4. Declare a tool",
    "5. Register it, offer it, and execute the result",
    "Where to go deeper"
  ],
  "source": "In this exercise you install the kernel, make a real model call, and declare a\ntool with a typed input schema. It runs locally and needs no account.\n\nEvery snippet below uses a symbol `@namzu/sdk` actually exports. The tool\nexamples are pulled by reference from the snippet registry\n(`snippets/greeter/agent.ts`) so they stay compile-checked and cannot rot.\n\n## Before you start\n\n- **Node.js 20 or later**, and a package manager. The commands use `pnpm`.\n- **TypeScript 5.5 or later**.\n- Optional, for the local model path: [Ollama](https://ollama.com) running on\n  `http://localhost:11434` with one model pulled.\n\n## 1. Install the kernel and one driver\n\nThe kernel and the vendor drivers are separate packages, so you install exactly\none vendor:\n\n```bash\npnpm add @namzu/sdk @namzu/ollama zod\n```\n\n> [!TIP]\n> If Ollama is not running, install only `@namzu/sdk` and skip ahead. The kernel\n> carries a pre-registered `MockLLMProvider`, so every step below still executes —\n> it simply answers from the mock instead of a model.\n\n## 2. Register a provider\n\nRegistration happens once, at startup. It is the only vendor-specific code in\nyour program:\n\n:::code language=\"typescript\" source=\"snippets/greeter/agent.ts\" id=\"snippet_register\":::\n\n## 3. Send your first call\n\n:::code language=\"typescript\" source=\"snippets/greeter/agent.ts\" id=\"snippet_chat\":::\n\nRun it. The response shape is the same for every driver:\n\n```typescript\n{ id, model, message: { role, content, toolCalls? }, finishReason, usage }\n```\n\nThat is the contract the kernel guarantees. A driver that cannot satisfy it is a\nbug in the driver, not something your code has to work around.\n\n## 4. Declare a tool\n\nA tool is an action with a typed input schema and a declared authority. Note what\n`defineTool` makes you state explicitly — this is the least-privilege model in\npractice, not a slogan:\n\n:::code language=\"typescript\" source=\"snippets/greeter/agent.ts\" id=\"snippet_tool\":::\n\nFour of those fields are declarations *about* the tool rather than behavior of\nit:\n\n| Field | What you are asserting |\n| --- | --- |\n| `permissions` | Exactly what the tool may reach. `[]` means it computes and reaches nothing. |\n| `readOnly` | Whether running it can change anything. |\n| `destructive` | Whether it can destroy something. May be a function of the input. |\n| `concurrencySafe` | Whether two invocations may overlap. |\n\nThe kernel uses these to decide what it is allowed to do on your behalf — for\nexample whether it may run a call in parallel, or whether it must stop and defer\nto a person.\n\n## 5. Register it, offer it, and execute the result\n\nA `ToolRegistry` owns your tools. It converts them into the provider-neutral wire\nformat with `toLLMTools()`, and it is what executes them - so validating the\nmodel's arguments is not your job:\n\n:::code language=\"typescript\" source=\"snippets/greeter/agent.ts\" id=\"snippet_toolcalls\":::\n\nThree things worth noticing:\n\n- `toolCalls` is the model's **request**, not an execution. Nothing runs until you\n  ask the registry to run it.\n- The registry validates arguments against your schema *before* invoking\n  `execute`, so it never has to defend against malformed input.\n- The `ToolContext` is where authority actually arrives at run time - the working\n  directory, the environment, the abort signal. A real runtime supplies it; the\n  snippet builds the minimum a standalone script needs.\n\n> [!CAUTION]\n> Do not widen a tool's `permissions` to make a call succeed. If a tool needs\n> more authority, that is a decision to make deliberately — and to record —\n> not a value to bump until an error stops appearing.\n\n## Where to go deeper\n\nThe kernel also covers sandboxing (`@namzu/sandbox`), telemetry over OTLP\n(`@namzu/telemetry`), file registry contracts, and a set of built-in tools such\nas `ReadFileTool`, `GrepTool`, and `BashTool`. The\n[packages reference](/docs/packages/) lists the published surface.\n",
  "partOf": "cogitave.learn.build-your-first-agent-with-namzu",
  "durationInMinutes": 12,
  "quiz": null
}