TypeScript

Better Agent infers types from your agents, schemas, tools, memory, and app registration. You do not need generated client types.

Agent names

Registered agent names become valid handles on the app.

const support = app.agent("support");

// TypeScript error when no registered agent has this name.
const billing = app.agent("billing");

The same name checking works in the browser when the client uses the server app type.

Context

contextSchema defines the context shape for runs, streams, instructions, tools, and hooks.

const analyst = defineAgent({
  name: "analyst",
  model: openai("gpt-5.5"),
  contextSchema: z.object({
    userId: z.string(),
    plan: z.enum(["free", "pro", "enterprise"]),
  }),
  instruction: (context) => `The user is on ${context.plan}.`,
});

await app.agent("analyst").run({
  messages,
  context: {
    userId: "usr_123",
    plan: "pro",
  },
});

See Agent for agent configuration.

Tools

Tool schemas infer the input type passed to server tools.

const searchDocs = defineTool({
  name: "search_docs",
  target: "server",
  description: "Search internal docs.",
  inputSchema: z.object({
    query: z.string(),
    limit: z.number().default(5),
  }),
  execute: async (input) => {
    return docs.search(input.query, { limit: input.limit });
  },
});

Client tool handlers infer the input for each matching client tool.

const agent = useAgent(client.agent("support"), {
  toolHandlers: {
    confirm_address: async (input) => {
      return openAddressDialog(input.address);
    },
  },
});

See Tools for server tools, client tools, approvals, MCP tools, and provider tools.

Structured output

output.schema infers result.structured.

const extractor = defineAgent({
  name: "extractor",
  model: openai("gpt-5.5"),
  output: {
    schema: z.object({
      title: z.string(),
      priority: z.enum(["low", "medium", "high"]),
    }),
  },
});

const result = await app.agent("extractor").run({ messages });

result.structured.priority;

See Structured Output for schema formats and per-run output.

Client type sharing

Export your server app and pass its type to the client.

// server.ts
export const app = betterAgent({
  agents: [supportAgent, analyst],
});

export default app;
// client.ts
import { createClient } from "@better-agent/client";
import type app from "@/better-agent/server";

export const client = createClient<typeof app>({
  baseURL: "/api/agents",
});

The client now knows agent names, context, memory helpers, and client tool handlers.

See Client for browser usage.

Schema types

Schemas can be Zod, any Standard Schema, or plain JSON Schema.

const schema = {
  type: "object",
  properties: {
    name: { type: "string" },
    tags: { type: "array", items: { type: "string" } },
  },
  required: ["name"],
  additionalProperties: false,
} as const;

Use as const with plain JSON Schema when you want narrower inferred types.

Helper types

TypePackageUse it for
AgentContextOf@better-agent/coreGet the context type from an agent.
InferSchemaInput@better-agent/coreInfer input from a schema.
InferSchemaOutput@better-agent/coreInfer output from a schema.
BetterAgentApp@better-agent/coreType an app when exporting helpers.
BetterAgentErrorCode@better-agent/coreType error-code handling.
AgentNameOf@better-agent/clientGet valid agent names from an app type.
AgentContextFor@better-agent/clientGet client context for one agent.
ToolHandlersFor@better-agent/clientType client tool handlers.