NylorunDocsBeta
BuildRunDeployReferenceMore

Capabilities

Add instructions, tools, and before/after hooks to an agent.

Add a named capability and attach it with .use(). The following snippet assumes an application-owned orders service; construct that client in the host.

import { Agent, capability, tool } from "@nylorun/agents";
import { z } from "zod";

type SupportInfo = { accountId?: string };
type OrderService = {
  find(
    orderNumber: string,
    options: { signal: AbortSignal; accountId?: string },
  ): Promise<{ orderNumber: string; status: string }>;
};

export function supportCapability(orders: OrderService) {
  const findOrder = tool({
    name: "find_order",
    description: "Find an order by its public order number.",
    input: z.object({ orderNumber: z.string() }),
    output: z.object({ orderNumber: z.string(), status: z.string() }),
    effects: "read",
    async run({ orderNumber }, context) {
      return orders.find(orderNumber, {
        signal: context.signal,
        accountId: context.info?.accountId,
      });
    },
  });

  return capability({
    id: "support",
    instructions: "Ask for an order number before using find_order.",
    tools: [findOrder],
  });
}

export const assistant = Agent({ id: "assistant", name: "Assistant" })
  .use(supportCapability(orders))
  .build();

Construct orders and other service clients in the application, then close over them in the capability. Per-session host data is info on the Runtime session (tools read context.info). Top-level tools and instructions on Agent({ ... }) are first-class and compile as capability id "agent". tools on either surface can include another Agent — see Subagents.

Understand hooks

Durable definitions use scoped hooks. They can add instructions, tools, or state, or deny / approve / retry / block a candidate. They cannot set model — Runtime owns model resolution.

ContributionDeclarative fieldDynamic API
Instructionsinstructionsbefore("turn"|"step")Patch
Toolstoolsbefore("turn"|"step")Patch
Session memorytools write context.statebefore reads state
After a model callafter("step")Decision
After the final answerafter("turn")TurnDecision

capability({ model }) is deprecated. Durable manifests reject arbitrary middleware closures. Use hooks.

Helpers such as mcp(), sandbox(), skills(), and plugin() each return one capability. See those pages for the options they accept.

Manage ordering and ownership

The application owns resources. Create clients in the host, close over them from tools, and shut them down in the application. There is no capability state factory.

Capabilities are applied in .use() order. Use stable, unique ids and separate declarations for independent concerns.

The published catalog row is capabilities[] with id, type (agent or agent-plugin), optional instructions, tools, skills, MCP servers, sandbox, and hooks: { at, scope }[].

Next step

On this page