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.
| Contribution | Declarative field | Dynamic API |
|---|---|---|
| Instructions | instructions | before("turn"|"step") → Patch |
| Tools | tools | before("turn"|"step") → Patch |
| Session memory | tools write context.state | before reads state |
| After a model call | — | after("step") → Decision |
| After the final answer | — | after("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 }[].