# Build and use Tools

> Turn governed Resource operations into clear model-facing capabilities with bounded schemas and truthful effect handling.

Tools do not introduce another integration layer. A Tool is the model-facing projection of code in one Agent package. When it derives from a Resource operation, deployment resolves that operation's pinned schema, effect, and Resource identity into the Agent's immutable Toolset.

In the Console, **Add Tool** opens the same package-source workflow as **Deploy Agent** because a custom Tool has no independent runtime or deployment lifecycle. Upload the Agent package or provide its immutable Git revision; deployment validates the Agent and Tool set together.

The Constal platform provider projects three reviewed authoring templates—`web_fetch`, `web_search`, and `cas`—once for every tenant. The Console shows these provider-owned templates alongside Agent-owned deployed ToolResources through the ordinary Resource collection. No tenant-local copies or separate execution path are created. Importing a template still requires the Agent to bind the Resource operations named by that template.

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

Configure the Resource and inspect its immutable operation catalog. Choose the smallest set of operations the model needs. A Tool should express one understandable outcome, validate a bounded argument object, and declare the maximum external effect it can produce.

## Use an existing capability {#existing-capabilities}

Use the SDK helper for the existing governed Web Resource:

```ts
import { agent, webFetch } from "@constal/sdk";

export default agent({
  id: "researcher", version: "1.0.0", model: "model",
  tools: { web_fetch: webFetch },
  async onMessage(message, ctx) {
    return ctx.turn({
      system: "Research the request using only the supplied sources.",
      objective: message,
      tools: ["web_fetch"],
    });
  },
});
```

`webFetch` resolves to the existing `web#get` operation. Web search resolves through the Agent's bound Search Resource:

```ts
import { webSearch } from "@constal/sdk";

export const search = webSearch;
```

Use the provider's CAS Tool only when the model needs to choose whether to store or load an artifact:

```ts
import { casTool } from "@constal/sdk";

export const cas = casTool;
```

Deterministic Agent code should continue using `store()` and `load()` from `@constal/artifacts` directly. Use `opTool(binding, op)` for any other existing operation. Deployment fails if a required binding or operation is unavailable; it never silently creates a second capability.

## Steps {#steps}

### Build a custom Tool {#custom-tools}

1. Define a Tool with a stable name and version, an optional one-line title, a concise outcome-oriented description, JSON schema, maximum effect, logical Resource needs, and handler.
2. Resolve the exact accepted Resource from `ctx.resources`; never accept a Resource CRN or owner identity from model arguments.
3. Invoke the pinned operation with `ctx.invoke()` or return the durable handle from `ctx.invokeAsync()`. Supply a stable dedupe key for idempotent external mutations.
4. Register the Tool in `agent.tools` and list its local name in `constal.agent.json`. The deployment pins the resulting Toolset.
5. Offer only the needed Tool names in `ctx.turn({ tools: [...] })`. Policy can narrow the offered set further at each turn.

```ts
import type { Tool } from "@constal/sdk";

export const lookupOrder: Tool = {
  name: "lookup_order", version: "1",
  title: "Read an order's status",
  description: "Read the current status of one order.",
  schema: { type: "object", required: ["orderId"], additionalProperties: false,
    properties: { orderId: { type: "string", minLength: 1, maxLength: 128 } } },
  maxEffect: "read-only",
  needs: [{ binding: "orders", kind: "db", ops: ["order.get"] }],
  run(args, ctx) { return ctx.invoke(ctx.resources.orders!, "order.get", args); },
};
```

The `title` is for people: the Console, the CLI, Tool approvals and Constal API summaries show it, or the Tool's name when it has none. The `description` is the model's prompt; the model never receives the title.

`opTool(binding, op)` and `opTools(binding, ops)` can derive catalog-backed Tools when the operation contract already supplies the correct schema and effect. Use a custom Tool when the model interface must be narrower or combine controlled steps.

In `constal.agent.json`, bind the exact Resources and include only the Tool names that deployment should expose:

```json constal.agent.json
{
  "bindings": {
    "model": "crn:constal:production:YOUR_TENANT:default:model/research",
    "web": "crn:constal:production:YOUR_TENANT:default:web/public",
    "search": "crn:constal:production:YOUR_TENANT:default:service/search",
    "cas": "crn:constal:production:YOUR_TENANT:default:cas/artifacts"
  },
  "tools": ["web_fetch", "web_search", "cas"]
}
```

The complete manifest also includes the normal schema version, Agent identity, entrypoint, mode, Policies, limits, and expected deployment revision. See [Set up an SDK project](/docs/sdk/project.md) for the complete file.

## Verify {#verify}

Deploy and inspect **Resources → Tools**. Confirm the Tool’s title (its name when it has none), owning Agent, version, needs, and enabled status. Start a Run and verify the journal records the Tool call and exact Resource operation separately, with the expected effect, Policy decision, usage, and outcome.

## Next steps {#next-steps}

Read [Resources and Tools](/docs/sdk/resources-and-tools.md), [Use Resources from Agents](/docs/resources/use.md), and [Operate Runs](/docs/runs/operate.md).
