Tools
Give the model a typed host-owned function the connected executor can run.
A tool exposes a host-owned function to the model. Prefer input / output /
run. A plain return is a completed result. Legacy inputSchema / execute
and tagged { kind: "completed" } outcomes still work.
import { Agent, tool } from "@nylorun/agents";
import { z } from "zod";
const lookupOrder = tool({
name: "lookup_order",
description: "Look up a sample order by ID. Try demo-123.",
input: z.object({ orderId: z.string() }),
output: z.object({ orderId: z.string(), status: z.string() }),
async run({ orderId }) {
return { orderId, status: orderId === "demo-123" ? "shipped" : "not found" };
},
});
export const assistant = Agent({
id: "assistant",
name: "Order assistant",
tools: [lookupOrder],
}).build();input validates model-generated arguments before execution. Add output when
downstream code relies on a specific completed result. Runtime checks a
successful tool result against that output schema and stores a mismatch as a
failed outcome. A valid schema is not authorization: check the current user in
the host service.
Execution context
Forward context.signal to network clients so cancellation stops in-flight
work. Context also includes idempotencyKey, optional redelivery, state,
session.id, and optional agent ({ id, path, delegationId? } — the root
agent, or the child when this call belongs to a delegation).
Durable wait helpers (ask, approve, sleep, waitFor,
step) exist on the context; automatic timer and event wakeups are not in this
release.
Code-only fields (never serialized into the manifest):
effects:"read" | "idempotent" | "write"approval: return a prompt string (ortrue) to pause beforerun
Connected execution versus the engine
The default path is a connected executor: the CLI (or connectAgents)
claims actions from Runtime and runs your implementations in the application
process.
| Behavior | Connected executor (connectAgents) | In-process engine (harness/run) |
|---|---|---|
| Invalid tool input | Failed result tool.invalid-input. The message is a JSON string of issues. There is no engine details: { phase, issues } shape. | Failed result tool.invalid-arguments with details: { phase, issues }. |
context.progress | No-op. Progress transport is not implemented on this path. | Emits a tool.progress observation when a listener is present. |
Document the mode you are using. Do not treat engine-only validation detail or live progress as part of the starter workflow.
Ownership
Construct service clients in the application and close over them from tools.
Per-session host data is info on the Runtime session (tools read
context.info). Definitions do not create clients, supply credentials, or
authorize external calls.
Tools belong in a capability so their ownership is visible. Use separate capabilities when tools depend on different services, credentials, or policies.
Sandbox tools (bash, read, write, edit, grep, glob) run in Runtime,
not in your executor. See Sandbox.
Put a built Agent in tools to let the model delegate a self-contained
task. The child becomes a tool named after its id and takes { task: string }.
See Subagents.