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

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

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

Build a custom Tool

  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:

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 for the complete file.

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

Read Resources and Tools, Use Resources from Agents, and Operate Runs.