---
title: "API Reference"
description: "Structural driver contracts, runtime results, configuration types, and events in XSAF."
---

> Documentation Index
> Fetch the complete documentation index at: https://xsaf.ilha.build/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

Import these contracts from `@xsaf/agent`. They are structural: custom drivers implement the interfaces directly without extending an XSAF base class.

For the fluent builder surface, start with the [`xsaf` API reference](/xsaf).

## Configuration

```ts
interface ServeConfig {
  transport: "http";
  path?: string;
  name?: string;
  version?: string;
  driver?: XsafServeDriver;
}
```

Default MCP path is `/mcp`; default name is the agent name or `xsaf`; default version is `0.1.0-alpha.0`. The built-in transport only mounts a route.

```ts
interface ScheduleConfig {
  cron: string;
  prompt: string | (() => Promise<string>);
  sessionId?: string;
  delegate?: string;
  onResult?: (result: AgentResult) => Promise<void>;
  timezone?: string;
  runImmediately?: boolean;
}
```

## Public contracts

XSAF drivers are narrow structural interfaces. Implement them without extending an XSAF base class.

### Results

```ts
interface AgentResult {
  text: string;
  usage?: Readonly<Record<string, number>>;
}

interface AgentStreamResult {
  textStream: AsyncIterable<string>;
  completed: Promise<AgentResult>;
}

type InvokeResult = AgentResult | AgentStreamResult;
```

### Model adapter

```ts
interface XsafModelAdapter {
  generate(request: ModelRequest): Promise<ModelResponse>;
  stream?(request: ModelRequest): ModelStreamResponse | Promise<ModelStreamResponse>;
  ask?<Output>(request: ModelRequest, schema: StandardSchemaV1<unknown, Output>): Promise<Output>;
}
```

`ModelRequest` contains model, endpoint, API key, messages, model-visible tools, maximum steps, and reasoning effort.

### Tool

```ts
interface ToolExecutionContext {
  sessionId: string;
  signal?: AbortSignal;
}

interface ToolConfig<Schema extends XsafToolSchema> {
  name: string;
  description: string;
  input: Schema;
  execute(
input: StandardSchemaV1.InferOutput<Schema>,
context: ToolExecutionContext,
  ): unknown | Promise<unknown>;
  approval?: "auto" | "human" | ApprovalFn;
  retries?: number;
  timeout?: number;
  onError?: (error: unknown) => unknown | Promise<unknown>;
  sandbox?: XsafSandboxDriver;
}
```

See [Tools](/recipes/tools#tool-schemas) for the dual-schema requirement.

### Memory

```ts
interface XsafMemoryDriver {
  get(sessionId: string): Promise<Message[]>;
  append(sessionId: string, message: Message): Promise<void>;
  clear(sessionId: string): Promise<void>;
  close?(): Promise<void>;
}
```

### Channel

```ts
interface XsafChannelDriver {
  name: string;
  listen(context: ChannelContext): void | Promise<void>;
  send(target: ChannelTarget, payload: ChannelPayload): Promise<void>;
  close?(): Promise<void>;
}

type ChannelTarget = string | Readonly<Record<string, unknown>>;
type ChannelPayload = string | AsyncIterable<string> | { text: string; meta?: unknown };
```

`ChannelContext` includes the shared Hono app, an inbound dispatch function, and a compatibility message registration hook.

### Sandbox

```ts
interface XsafSandboxDriver {
  name: string;
  permissions?: SandboxPermissions;
  run(
fn: (...args: unknown[]) => Promise<unknown>,
args: unknown[],
options?: { signal?: AbortSignal },
  ): Promise<unknown>;
  close?(): Promise<void>;
}
```

### MCP

```ts
interface XsafMcpDriver {
  name: string;
  trust?: "trusted" | "untrusted";
  connect(context: McpContext): Promise<McpConnection | void>;
  close?(): Promise<void>;
}
```

A connection can provide tools, `resources.get(uri)`, and `prompts.get(name, args)`.

### Scheduler

```ts
interface XsafSchedulerDriver {
  schedule(config: ScheduleConfig, run: () => Promise<void>): Promise<ScheduledTask>;
}

interface ScheduledTask {
  close(): Promise<void>;
}

interface ParsedCron {
  readonly fields: readonly Set<number>[];
  matches(date: Date, timezone: string): boolean;
}

function parseCron(expression: string): ParsedCron;
```

Driver methods may close external resources, so start them only from lifecycle hooks. Keep optional runtime-specific imports out of core-facing contract modules and avoid leaking mutable registries through driver APIs.

## Events

Register typed handlers while configuring the builder:

```ts
builder.on("tool.failed", (event) => {
  console.error(event.tool, event.sessionId);
});
```

Handlers can be synchronous or asynchronous. Event failures are isolated so they cannot corrupt runtime state.

| Event                 | Payload fields               |
| --------------------- | ---------------------------- |
| `tool.called`         | `tool`, `sessionId`          |
| `tool.completed`      | `tool`, `sessionId`          |
| `tool.failed`         | `tool`, `sessionId`, `error` |
| `delegate.started`    | `delegate`, `sessionId`      |
| `delegate.completed`  | `delegate`, `sessionId`      |
| `message.sent`        | `channel?`, `sessionId`      |
| `approval.required`   | `tool`, `sessionId`          |
| `approval.granted`    | `tool`, `sessionId`          |
| `mcp.connected`       | `server`                     |
| `heartbeat.fired`     | `sessionId`                  |
| `heartbeat.completed` | `sessionId`                  |
| `heartbeat.failed`    | `sessionId`, `error`         |
| `sandbox.escalated`   | `sandbox`, `tool`            |
| `sandbox.denied`      | `sandbox`, `tool`, `reason`  |

`sandbox.escalated` and `sandbox.denied` are public event variants for sandbox integrations. The bundled local and host adapters do not emit them.

```ts
type EventType = XsafEvent["type"];
type EventFor<Type extends EventType> = Extract<XsafEvent, { type: Type }>;
type EventHandler<Type extends EventType> = (event: EventFor<Type>) => unknown | Promise<unknown>;
```

`approval.required` does not carry tool arguments. Register `.approve(handler)` for privileged approval decisions that require validated input. Failure events expose a string error message; classify and redact it before exporting telemetry. Never serialize raw authorization headers, API keys, MCP payloads, channel metadata, or memory content by default.

A schedule emits `heartbeat.fired` before running. Success emits `heartbeat.completed`; failure emits `heartbeat.failed`. Overlapping ticks are skipped and do not emit a second `heartbeat.fired` for work that never starts.

## See also

- [Builder and lifecycle](/xsaf)
- [Tools & Security](/recipes/tools)
- [MCP](/xsaf/mcp)
- [Delegation](/xsaf/delegate)
- [Scheduling](/xsaf/schedule)
- [Roadmap](/roadmap)

Source: https://xsaf.ilha.build/reference/index.mdx
