### Install Dependencies and Run Dev Server
Source: https://github.com/better-agent/better-agent/blob/main/examples/tanstack/README.md
Installs project dependencies and starts the development server.
```bash
npm install
npm run dev
```
--------------------------------
### Install AI SDK Packages
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/ai-sdk/page.mdx
Install the necessary npm packages for the AI SDK and its provider. The example uses OpenAI.
```bash
npm install @better-agent/ai-sdk ai @ai-sdk/openai
```
--------------------------------
### Run Scaffold with Options
Source: https://github.com/better-agent/better-agent/blob/main/packages/create/README.md
Provide scaffold options directly via command-line arguments for non-interactive setup. This allows specifying framework, providers, plugins, and installation behavior.
```bash
npm create better-agent my-agent-app -- --framework nextjs --providers openai --plugins logging --no-install
```
--------------------------------
### Install @better-agent/xai
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/xai/page.mdx
Install the xAI package using npm.
```bash
npm install @better-agent/xai
```
--------------------------------
### Install E2B and Daytona SDKs
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Install the necessary SDKs for E2B and Daytona to use the sandbox plugin.
```bash
npm install e2b
npm install @daytonaio/sdk
```
--------------------------------
### Install Prisma Adapter and Dependencies
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/prisma/page.mdx
Install the Prisma adapter for Better Agent along with Prisma client and Prisma itself.
```bash
npm install @better-agent/prisma @prisma/client prisma
```
--------------------------------
### Copy Environment File
Source: https://github.com/better-agent/better-agent/blob/main/examples/tanstack/README.md
Copies the example environment file to a new file for configuration.
```bash
cp .env.example .env
```
--------------------------------
### Install Fastify Adapter
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/fastify/page.mdx
Install the necessary npm package for the Fastify adapter.
```bash
npm install @better-agent/adapters
```
--------------------------------
### Install Dependencies with Bun
Source: https://github.com/better-agent/better-agent/blob/main/CONTRIBUTING.md
Installs project dependencies using Bun. Ensure Node.js and Bun are installed.
```sh
bun install
```
--------------------------------
### Install OpenAI Package
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/openai/page.mdx
Install the OpenAI provider package for Better Agent.
```bash
npm install @better-agent/openai
```
--------------------------------
### Install Redis Adapter
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/redis/page.mdx
Install the necessary packages for the Redis adapter using npm.
```bash
npm install @better-agent/redis redis
```
--------------------------------
### Install Gemini Provider
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/gemini/page.mdx
Install the Gemini provider package using npm.
```bash
npm install @better-agent/gemini
```
--------------------------------
### Install OpenRouter Package
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/openrouter/page.mdx
Install the OpenRouter package using npm.
```bash
npm install @better-agent/openrouter
```
--------------------------------
### Install Kysely and PostgreSQL Driver
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/kysely/page.mdx
Install the Kysely adapter for Better Agent along with the Kysely core library and the PostgreSQL driver.
```bash
npm install @better-agent/kysely kysely pg
```
--------------------------------
### Install Drizzle Adapter and Dependencies
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/drizzle/page.mdx
Install the Drizzle adapter for Better Agent along with Drizzle ORM and the PostgreSQL driver.
```bash
npm install @better-agent/drizzle drizzle-orm pg
```
--------------------------------
### Setup Prisma Storage in Better Agent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/prisma/page.mdx
Initialize Better Agent with the Prisma storage adapter by passing an existing Prisma client instance.
```typescript
import { betterAgent } from "@better-agent/core";
import { prismaStorage } from "@better-agent/prisma";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export const app = betterAgent({
storage: prismaStorage({
client: prisma,
}),
agents: [supportAgent],
});
```
--------------------------------
### Install Better Agent Core and OpenAI Provider
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/get-started/page.mdx
Install the necessary packages for Better Agent and the OpenAI provider using npm.
```bash
npm install @better-agent/core @better-agent/openai
```
--------------------------------
### Install Ollama Provider
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/ollama/page.mdx
Install the Ollama provider package using npm.
```bash
npm install @better-agent/ollama
```
--------------------------------
### Server-side Agent Setup
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/sveltekit/page.mdx
Configure the Better Agent with OpenAI on the server. Ensure your OpenAI API key is available in the environment variables.
```typescript
// src/lib/better-agent/server.ts
import { env } from "$env/dynamic/private";
import { betterAgent, defineAgent } from "@better-agent/core";
import { createOpenAI } from "@better-agent/openai";
const openai = createOpenAI({
apiKey: env.OPENAI_API_KEY,
});
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
});
const app = betterAgent({
agents: [supportAgent],
basePath: "/api/agents",
});
export default app;
```
--------------------------------
### Basic Logging Setup
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/logging/page.mdx
Initializes the better-agent with the logging plugin. By default, logs are sent to the console, all logging groups are enabled, and the minimum level is 'info'.
```typescript
import { betterAgent } from "@better-agent/core";
import { logging } from "@better-agent/plugins";
export const app = betterAgent({
agents: [supportAgent],
plugins: [logging()],
});
```
--------------------------------
### Install Anthropic Provider
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/anthropic/page.mdx
Install the Anthropic provider package using npm.
```bash
npm install @better-agent/anthropic
```
--------------------------------
### Setup Better Agent Server
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/elysia/page.mdx
Defines and configures the Better Agent server with specified agents. This code should be placed in your server setup file.
```typescript
// lib/better-agent/server.ts
import { betterAgent, defineAgent } from "@better-agent/core";
import { openai } from "@better-agent/openai";
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
});
const app = betterAgent({
agents: [supportAgent],
basePath: "/api/agents",
});
export default app;
```
--------------------------------
### Server API Route Setup
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/astro/page.mdx
Defines the Better Agent server instance with a support agent and configures the base API path.
```typescript
// src/lib/better-agent/server.ts
import { betterAgent, defineAgent } from "@better-agent/core";
import { openai } from "@better-agent/openai";
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
});
const app = betterAgent({
agents: [supportAgent],
basePath: "/api/agents",
});
export default app;
```
--------------------------------
### Install CORS Middleware
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/express/page.mdx
Install the CORS package to handle cross-origin requests.
```bash
npm install cors
```
--------------------------------
### Install Workers AI Package
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/workers-ai/page.mdx
Install the necessary package for using Workers AI with Better Agent.
```bash
npm install @better-agent/workers-ai
```
--------------------------------
### Run Interactive Scaffold
Source: https://github.com/better-agent/better-agent/blob/main/packages/create/README.md
Execute the interactive command to scaffold a new Better Agent app. This is the default way to start a new project.
```bash
npm create better-agent
```
--------------------------------
### Basic Rate Limiting Setup
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/rate-limit/page.mdx
Configure a global rate limit for all requests within a specified time window. This is suitable for single-instance applications or local development.
```typescript
import { betterAgent } from "@better-agent/core";
import { rateLimit } from "@better-agent/plugins";
export const app = betterAgent({
agents: [supportAgent],
plugins: [
rateLimit({
windowMs: 60_000,
max: 100,
}),
],
});
```
--------------------------------
### Install Fastify CORS
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/fastify/page.mdx
Install the CORS plugin for Fastify to handle cross-origin requests.
```bash
npm install @fastify/cors
```
--------------------------------
### Connect to MCP Servers and Expose Tools
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
Use `mcpTools` to connect to Model Context Protocol servers and expose their tools to an agent. This example connects to GitHub and a local filesystem server.
```typescript
import { mcpTools } from "@better-agent/core/mcp";
const mcp = mcpTools({
servers: {
github: {
transport: {
type: "http",
url: "https://api.githubcopilot.com/mcp",
},
},
filesystem: {
transport: {
type: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "./data"],
},
},
},
});
const agent = defineAgent({
name: "dev",
model: openai("gpt-5.5"),
instruction: "You help with development tasks.",
tools: async (ctx) => [searchTool, ...(await mcp(ctx))],
});
```
--------------------------------
### Configure In-Memory Storage
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/storage/page.mdx
Configure in-memory storage for local development and tests. This is a simple setup for quick iteration.
```typescript
import { betterAgent, createInMemoryStorage } from "@better-agent/core";
export const app = betterAgent({
storage: createInMemoryStorage(),
agents: [supportAgent],
});
```
--------------------------------
### Server-side Agent Setup in Remix
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/remix/page.mdx
Configure the Better Agent server instance within a Remix lib file. This sets up the agents and their base path for API communication.
```typescript
// app/lib/better-agent/server.ts
import { betterAgent, defineAgent } from "@better-agent/core";
import { openai } from "@better-agent/openai";
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
});
const app = betterAgent({
agents: [supportAgent],
basePath: "/api/agents",
});
export default app;
```
--------------------------------
### Setup Drizzle Storage with Better Agent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/drizzle/page.mdx
Configure Better Agent to use Drizzle as its storage adapter by providing a Drizzle database instance and dialect.
```typescript
import { betterAgent } from "@better-agent/core";
import { drizzleStorage } from "@better-agent/drizzle";
import { drizzle } from "drizzle-orm/node-postgres";
import { Client } from "pg";
import * as betterAgentSchema from "./better-agent.schema";
const client = new Client({
connectionString: process.env.DATABASE_URL,
});
await client.connect();
const db = drizzle({
client,
schema: {
...betterAgentSchema,
},
});
export const app = betterAgent({
storage: drizzleStorage({
db,
dialect: "postgres",
}),
agents: [supportAgent],
});
```
--------------------------------
### Configure Sandbox Creation Settings
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Set fixed creation settings for the sandbox using `createConfig` and fallback settings with `createDefaults`. This example specifies a Node.js 20 template and development environment variables.
```typescript
const plugin = sandbox({
client: createDaytonaSandboxClient({
apiKey: process.env.DAYTONA_API_KEY,
}),
createConfig: {
template: "node:20",
envs: {
NODE_ENV: "development",
},
},
createDefaults: {
startupTimeoutMs: 90_000,
},
});
```
--------------------------------
### Basic Chat Component
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/sveltekit/page.mdx
Implement a basic chat interface using the `createAgentChat` Svelte store. This example demonstrates sending messages and displaying chat history and errors.
```svelte
```
--------------------------------
### Plugin Guard Example
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/auth/page.mdx
Implement a plugin guard to enforce authentication. This guard returns an unauthorized response if no auth context is present.
```typescript
const workspaceGuard = definePlugin({
id: "workspace-guard",
guards: [
async ({ auth }) => {
return auth ? null : new Response("Unauthorized", { status: 401 });
},
],
});
```
--------------------------------
### Providing Tools via a Plugin
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/plugins/page.mdx
This example shows how a plugin can expose custom tools to agents. It defines a `currentTime` tool using `defineTool` and registers it within the plugin using the `tools` property.
```typescript
import { definePlugin, defineTool } from "@better-agent/core";
import { z } from "zod";
const currentTime = defineTool({
name: "current_time",
target: "server",
description: "Return the current UTC time.",
inputSchema: z.object({}),
execute: async () => ({ time: new Date().toISOString() }),
});
export const time = definePlugin({
id: "time",
tools: [currentTime],
});
```
--------------------------------
### Configure App Memory
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/memory/page.mdx
Configure memory for the entire application using `createMemory`. This example sets the history window to the last 20 messages.
```typescript
import { betterAgent, createMemory } from "@better-agent/core";
export const app = betterAgent({
storage,
memory: createMemory({ lastMessages: 20 }),
agents: [supportAgent],
});
```
--------------------------------
### Agent Access with Capabilities
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/auth/page.mdx
Require specific agent capabilities for access. This example ensures only callers with the 'support_chat' capability can run the support agent.
```typescript
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
access: ({ auth }) => auth?.scopes?.includes("support_chat") ?? false,
});
```
--------------------------------
### Setup Kysely Storage with Better Agent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/kysely/page.mdx
Configure Better Agent to use Kysely for storage by passing a Kysely database instance to the `kyselyStorage` function. Ensure your Kysely instance is correctly initialized with a dialect and connection pool.
```typescript
import {
betterAgent,
} from "@better-agent/core";
import {
kyselyStorage,
} from "@better-agent/kysely";
import { Kysely, PostgresDialect } from "kysely";
import { Pool } from "pg";
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({
connectionString: process.env.DATABASE_URL,
}),
}),
});
export const app = betterAgent({
storage: kyselyStorage({
db,
dialect: "postgres",
}),
agents: [supportAgent],
});
```
--------------------------------
### Resume an Interrupted Client Tool Run
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
This example shows how to manually resume an agent run after it was interrupted by a client tool, providing the necessary thread ID and resolution payload.
```typescript
const threadId = "thread_123";
const result = await app.agent("support").run({ threadId, messages });
if (result.outcome === "interrupt") {
const interrupt = result.interrupts[0];
await app.agent("support").run({
threadId,
resume: [
{
interruptId: interrupt.id,
status: "resolved",
payload: { status: "success", result: { confirmed: true } },
},
],
});
}
```
--------------------------------
### Setup Redis Storage with Better Agent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/redis/page.mdx
Configure Better Agent to use Redis for storage by passing a connected Redis client. Ensure the Redis client is connected before passing it to the storage adapter.
```typescript
import {
betterAgent,
} from "@better-agent/core";
import {
redisStorage,
} from "@better-agent/redis";
import {
createClient,
} from "redis";
const client = await createClient({
url: process.env.REDIS_URL,
}).connect();
export const app = betterAgent({
storage: redisStorage({
client,
}),
agents: [supportAgent],
});
```
--------------------------------
### Customize Sandbox Tool Prefixes
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Customize the tool names used by the sandbox plugin by setting a prefix. This example sets the prefix to 'workspace'.
```typescript
const plugin = sandbox({
prefix: "workspace",
client: createE2BSandboxClient({
apiKey: process.env.E2B_API_KEY,
}),
});
```
--------------------------------
### Control Sandbox Reuse with Session Key
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Configure sandbox reuse by providing a `sessionKey` function. This example reuses sandboxes based on agent name and thread ID.
```typescript
const plugin = sandbox({
client: createE2BSandboxClient({
apiKey: process.env.E2B_API_KEY,
}),
sessionKey: ({ agentName, threadId }) => {
if (!threadId) return undefined;
return `${agentName}:${threadId}`;
},
});
```
--------------------------------
### Define Tool with Conditional Approval
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
Use the `approval: { resolve: ... }` option for conditional approval based on tool input. This example refunds an order only if the amount exceeds 50.
```typescript
const refundTool = defineTool({
name: "refund",
target: "server",
description: "Issue a refund.",
inputSchema: z.object({ orderId: z.string(), amount: z.number() }),
approval: {
resolve: ({ toolInput }) => toolInput.amount > 50,
},
async execute({ orderId, amount }) {
return stripe.refunds.create({ payment_intent: orderId, amount });
},
});
```
--------------------------------
### Define Plugin with HTTP Endpoint
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/plugins/page.mdx
Example of defining a plugin with a GET endpoint at /health. The handler returns a JSON response.
```typescript
const health = definePlugin({
id: "health",
endpoints: [
{
method: "GET",
path: "/health",
handler: async () => Response.json({ ok: true }),
},
],
});
```
--------------------------------
### Defining a Custom Plugin
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/plugins/page.mdx
This example demonstrates the basic structure for defining a custom plugin using `definePlugin`. Each plugin requires a unique `id` and can implement various lifecycle hooks like `onEvent` for custom logic.
```typescript
import { definePlugin } from "@better-agent/core";
export const analytics = definePlugin({
id: "analytics",
onEvent: async (event, ctx) => {
await trackEvent({
type: event.type,
runId: ctx.runId,
agent: ctx.agentName,
});
},
});
```
--------------------------------
### Basic Chat Interface with useAgent Hook
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/remix/page.mdx
Implement a basic chat UI in a Remix component using the `useAgent` hook. This example shows sending messages and displaying agent responses.
```tsx
import { useAgent } from "@better-agent/client/react";
import { useState } from "react";
import { client } from "../lib/better-agent/client";
export default function ChatPage() {
const [input, setInput] = useState("");
const agent = useAgent(client.agent("support"), {
threadId: "main",
});
return (
);
}
```
--------------------------------
### Run and Stream Agent Interactions
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/agent/page.mdx
Register agents with `betterAgent` and execute them using `.run()` for a final result or `.stream()` for real-time event processing. This example shows how to initiate a run and consume streamed events.
```typescript
import { betterAgent } from "@better-agent/core";
const app = betterAgent({ agents: [agent] });
const result = await app.agent("support").run({
messages: [{ role: "user", content: "I need a refund." }],
});
const stream = await app.agent("support").stream({
messages: [{ role: "user", content: "I need a refund." }],
});
for await (const event of stream.events) {
console.log(event.type);
}
```
--------------------------------
### Observe Events in React with onEvent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/events/page.mdx
Use the `onEvent` hook in React to observe events for observability or custom UI behavior. This example logs tool call start events.
```tsx
import { EventType } from "@better-agent/core";
import { useAgent } from "@better-agent/client/react";
import { client } from "@/better-agent/client";
function Chat() {
const agent = useAgent(client.agent("support"), {
onEvent(event) {
if (event.type === EventType.TOOL_CALL_START) {
console.log("tool started", event.toolCallName);
}
},
});
return ;
}
```
--------------------------------
### Loading and Switching Threads
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/sveltekit/page.mdx
Manage conversation history by using helper functions to load messages, switch between different threads, or clear the current thread to start a new conversation.
```svelte
```
--------------------------------
### Stream Events from Agent Run
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/events/page.mdx
Use `.stream()` to receive events as they happen. Await `final` to get the finished run result. This example processes text message deltas and logs the final result.
```typescript
import { EventType } from "@better-agent/core";
const stream = await app.agent("support").stream({
messages: [{ role: "user", content: "Check my order status." }],
});
for await (const event of stream.events) {
if (event.type === EventType.TEXT_MESSAGE_CONTENT) {
process.stdout.write(event.delta);
}
}
const result = await stream.final;
```
--------------------------------
### Rate Limiting with Shared Storage
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/rate-limit/page.mdx
Implement rate limiting across multiple server instances by using a shared storage mechanism. This example demonstrates a custom in-memory store, but it can be adapted for external databases or caches.
```typescript
const rows = new Map();
const plugin = rateLimit({
windowMs: 60_000,
max: 100,
storage: {
async read({ bucket }) {
return rows.get(bucket.id) ?? null;
},
async write({ bucket, prevVersion, next }) {
const current = rows.get(bucket.id) ?? null;
if (prevVersion === null) {
if (current) return false;
rows.set(bucket.id, next);
return true;
}
if (!current || current.version !== prevVersion) return false;
rows.set(bucket.id, next);
return true;
},
},
});
```
--------------------------------
### Create a Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/client/page.mdx
Initialize the client by passing the server app type and the base URL for the agent handler. Ensure the baseURL points to the route where your app handler is mounted.
```typescript
import { createClient } from "@better-agent/client";
import type app from "@/better-agent/server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### Create Composite Storage with Table Routing
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/storage/page.mdx
Route a single storage area to a specific backend using composite storage for finer control. This example routes 'streamEvents' to Redis while using PostgreSQL as the default.
```typescript
const storage = createCompositeStorage({
default: postgresStorage,
tables: {
streamEvents: redisStorage,
},
});
```
--------------------------------
### Run Prisma Migrations and Generate Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/prisma/page.mdx
After updating your Prisma schema, run database migrations and generate the Prisma client.
```bash
npx prisma migrate dev
npx prisma generate
```
--------------------------------
### Create a Support Ticket Tool
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
This server tool demonstrates creating a support ticket, including priority levels and using context for agent and run information.
```typescript
const createTicket = defineTool({
name: "create_ticket",
target: "server",
description: "Create a support ticket.",
inputSchema: z.object({
subject: z.string(),
body: z.string(),
priority: z.enum(["low", "medium", "high"]),
}),
async execute(input, ctx) {
const ticket = await db.tickets.create({
...input,
createdBy: ctx.agentName,
runId: ctx.runId,
});
return { ticketId: ticket.id };
},
});
```
--------------------------------
### Running an Agent with Context
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/agent/page.mdx
Demonstrates how to run an agent, passing specific context data that matches the agent's defined context schema.
```typescript
await app.agent("analyst").run({
messages,
context: { userId: "usr_123", plan: "pro" },
});
```
--------------------------------
### Instantiate Image and Video Generation Models
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/xai/page.mdx
Create instances for image and video generation models. These are used for direct generation tasks.
```typescript
const image = xai.image("grok-2-image");
const video = xai.video("grok-video");
```
--------------------------------
### Agent Access Control
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/auth/page.mdx
Define agent access using the `access` property. This example restricts access to users with the 'admin' scope.
```typescript
const adminAgent = defineAgent({
name: "admin",
model: openai("gpt-5.5"),
instruction: "You help admins manage the workspace.",
access: ({ auth }) => auth?.scopes?.includes("admin") ?? false,
});
```
--------------------------------
### Client Initialization
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/sveltekit/page.mdx
Initialize the Better Agent client for use in your SvelteKit frontend. Align the `baseURL` with the server's `basePath` and the API route.
```typescript
// src/lib/better-agent/client.ts
import { createClient } from "@better-agent/client";
import type app from "$lib/better-agent/server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### Configure Gemini Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/gemini/page.mdx
Create a Gemini client instance, typically requiring an API key.
```typescript
import { createGemini } from "@better-agent/gemini";
const gemini = createGemini({
apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
});
```
--------------------------------
### Scaffold a Better Agent Project with CLI
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/get-started/page.mdx
Use the npx command to create a new Better Agent project with a full framework scaffold.
```bash
npx create-better-agent
```
--------------------------------
### Configure xAI Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/xai/page.mdx
Create an xAI client instance, typically used for direct model calls or tool integrations. Requires an API key from environment variables.
```typescript
import { createXai } from "@better-agent/xai";
const xai = createXai({
apiKey: process.env.XAI_API_KEY,
});
```
--------------------------------
### Initialize Agent Run with State
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/state/page.mdx
Pass an initial state object when starting an agent run. The final state is available in the run result.
```typescript
const result = await app.agent("support").run({
messages,
state: {
step: "triage",
selectedOrderId: null,
},
});
console.log(result.state);
```
--------------------------------
### Configure E2B Sandbox Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Set up the sandbox plugin with the E2B client, requiring an E2B API key.
```typescript
import { betterAgent } from "@better-agent/core";
import { createE2BSandboxClient, sandbox } from "@better-agent/plugins";
export const app = betterAgent({
agents: [coderAgent],
plugins: [
sandbox({
client: createE2BSandboxClient({
apiKey: process.env.E2B_API_KEY,
}),
}),
],
});
```
--------------------------------
### Update State from Server Tool
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/state/page.mdx
Server-side tools can read and modify the execution context's state using `state.patch()`. This example updates the `selectedOrderId`.
```typescript
const selectOrder = defineTool({
name: "select_order",
target: "server",
description: "Select the order being handled.",
inputSchema: z.object({
orderId: z.string(),
}),
execute: async (input, { state }) => {
state.patch([{ op: "replace", path: "/selectedOrderId", value: input.orderId }]);
return { selected: true };
},
});
```
--------------------------------
### Implement Shared Sandbox Store
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Use a custom `store` object to manage sandbox reuse across different workers or instances, using Redis as an example.
```typescript
const plugin = sandbox({
client: createE2BSandboxClient({
apiKey: process.env.E2B_API_KEY,
}),
store: {
get: async (key) => redis.get(key),
set: async (key, sandboxId) => {
await redis.set(key, sandboxId);
},
delete: async (key) => {
await redis.del(key);
},
},
});
```
--------------------------------
### Configure Multiple MCP Servers with Prefixes
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/mcp/page.mdx
Combine tools from multiple MCP servers, such as GitHub and a local filesystem, into a single tool source. Use the `prefix` option to prevent tool name collisions.
```typescript
const tools = mcpTools({
servers: {
github: {
transport: { type: "http", url: "https://api.githubcopilot.com/mcp" },
prefix: "gh",
},
filesystem: {
transport: {
type: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "./data"],
},
prefix: "fs",
},
},
});
```
--------------------------------
### Add Provider-Specific Tools like Web Search
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
Providers like OpenAI offer built-in tools. Use the provider helper, e.g., `openai.tools.webSearch`, to add them to an agent's toolset.
```typescript
import { openai } from "@better-agent/openai";
const agent = defineAgent({
name: "researcher",
model: openai("gpt-5.5"),
instruction: "Research the topic using web search.",
tools: [
openai.tools.webSearch({
searchContextSize: "medium",
}),
summarizeTool,
],
});
```
--------------------------------
### Nuxt Client Initialization
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/nuxt/page.mdx
Set up the Better Agent client for use in your Nuxt application. This client is typed against your server configuration.
```typescript
// lib/better-agent/client.ts
import { createClient } from "@better-agent/client";
import type app from "./server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### Configure Agent-Specific Memory
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/memory/page.mdx
Define an agent with its own memory configuration, overriding or supplementing app-level memory. This example sets a history window of 50 messages for the support agent.
```typescript
const supportAgent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: "You help customers.",
memory: createMemory({ lastMessages: 50 }),
});
```
--------------------------------
### Define a Server Tool
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
Use `defineTool` to create a server-side tool. Provide a name, target, description, input schema, and an execute function.
```typescript
import { defineTool } from "@better-agent/core";
import { z } from "zod";
const getWeather = defineTool({
name: "get_weather",
target: "server",
description: "Get the current weather for a location.",
inputSchema: z.object({
location: z.string(),
}),
async execute({ location }) {
const res = await fetch(`https://api.weather.com/${location}`);
return res.json();
},
});
```
--------------------------------
### Error Shape Example
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/errors/page.mdx
HTTP errors return problem details in a structured JSON format. Use `status` for transport handling, `code` for app logic, and `detail` for the message.
```json
{
"type": "https://better-agent.com/docs/concepts/errors#validation-failed",
"title": "Unprocessable Entity",
"status": 422,
"detail": "Invalid input.",
"code": "VALIDATION_FAILED",
"issues": []
}
```
--------------------------------
### Run Development Scripts with Bun
Source: https://github.com/better-agent/better-agent/blob/main/CONTRIBUTING.md
Executes common development scripts like build, typecheck, lint, and check using Bun. Use 'bun run check' for behavioral changes.
```sh
bun run build
bun run typecheck
bun run lint:ci
bun run check
```
--------------------------------
### AI SDK Text Generation Wrapper
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/ai-sdk/page.mdx
Use `aiSdkTextModel` for direct text generation calls outside the agent loop, commonly from server tools. This example defines a 'summarize' tool.
```typescript
import {
aiSdkTextModel,
aiSdkEmbeddingModel,
aiSdkImageModel,
} from "@better-agent/ai-sdk";
const text = aiSdkTextModel({
model: openai("gpt-5.5"),
providerId: "openai",
modelId: "gpt-5.5",
});
const summarize = defineTool({
name: "summarize",
description: "Summarize text with an AI SDK model.",
inputSchema: z.object({
content: z.string(),
}),
execute: async ({ content }) => {
const result = await text.generate({
input: `Summarize this in three bullets:\n\n${content}`,
});
return { summary: result.text };
},
});
```
--------------------------------
### Configure Custom Ollama Server
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/ollama/page.mdx
Create an Ollama instance when your server is not at the default location. Specify the baseURL for custom configurations.
```typescript
import { createOllama } from "@better-agent/ollama";
const ollama = createOllama({
baseURL: "http://localhost:11434/api",
});
```
--------------------------------
### Better Agent Client Initialization
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/astro/page.mdx
Creates a typed client instance for interacting with the Better Agent API, specifying the base URL.
```typescript
// src/lib/better-agent/client.ts
import { createClient } from "@better-agent/client";
import type app from "./server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### Tool Approval UI
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/sveltekit/page.mdx
Render UI for server tools that require user approval by iterating over `$chat.pendingToolApprovals`. Provide buttons to approve or reject the tool call.
```svelte
{#each $chat.pendingToolApprovals as approval (approval.interruptId)}
{approval.toolName}
{/each}
```
--------------------------------
### Create Typed Client Instance
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/typescript/page.mdx
Creates a typed client instance by importing the server app's type. This provides the client with knowledge of agent names, context, memory helpers, and client tool handlers.
```typescript
// client.ts
import { createClient } from "@better-agent/client";
import type app from "@/better-agent/server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### Basic Chat Interface with useAgent Hook
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/nuxt/page.mdx
Implement a basic chat interface in a Nuxt Vue component using the `useAgent` hook. This example shows sending messages and displaying agent responses.
```vue
```
--------------------------------
### Client with Request Rewriting
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/client/page.mdx
Customize outgoing requests using the `prepareRequest` option. This function allows you to modify request headers, bodies, or other properties before the request is sent, for example, to add a unique request ID.
```typescript
const client = createClient({
baseURL: "/api/agents",
prepareRequest(request) {
request.headers.set("x-request-id", crypto.randomUUID());
return request;
},
});
```
--------------------------------
### Use Existing MCP Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/mcp/page.mdx
Configure `mcpTools` to use an already created and connected MCP `Client` instance by passing it via the `client` option.
```typescript
mcpTools({
servers: {
internal: {
client: existingClient,
},
},
});
```
--------------------------------
### Configure Daytona Sandbox Client
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/sandbox/page.mdx
Configure the sandbox plugin with the Daytona client, including API key, target, template kind, and creation settings.
```typescript
import { betterAgent } from "@better-agent/core";
import {
createDaytonaSandboxClient,
sandbox,
} from "@better-agent/plugins";
export const app = betterAgent({
agents: [coderAgent],
plugins: [
sandbox({
client: createDaytonaSandboxClient({
apiKey: process.env.DAYTONA_API_KEY,
target: process.env.DAYTONA_TARGET,
templateKind: "image",
}),
createConfig: {
template: "node:20",
lifecycle: {
idleStopMs: 60 * 60_000,
},
},
}),
],
});
```
--------------------------------
### SolidStart API Route Handler
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/solidstart/page.mdx
Creates a catch-all API route in SolidStart to handle requests for the Better Agent, forwarding them to the server app handler.
```typescript
// src/routes/api/agents/[...path]/index.ts
import type { APIEvent } from "@solidjs/start/server";
import app from "../../../../lib/better-agent/server";
const handle = (event: APIEvent) => app.handler(event.request);
export const GET = handle;
export const POST = handle;
export const PUT = handle;
export const PATCH = handle;
export const DELETE = handle;
export const OPTIONS = handle;
export const HEAD = handle;
```
--------------------------------
### Configure Provider Options at Runtime
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/xai/page.mdx
Pass provider-specific options, such as 'reasoningEffort', to the xAI provider during an agent's run.
```typescript
await app.agent("support").run({
messages,
providerOptions: {
xai: {
reasoningEffort: "medium",
},
},
});
```
--------------------------------
### Client-side Better Agent Initialization
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/remix/page.mdx
Create a typed client instance for Better Agent in Remix. This client is used to interact with the server-side agent routes.
```typescript
// app/lib/better-agent/client.ts
import { createClient } from "@better-agent/client";
import type app from "./server";
export const client = createClient({
baseURL: "/api/agents",
});
```
--------------------------------
### List Threads and Messages
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/client/page.mdx
Access memory helpers to list saved threads and messages. Use `client.agent('name').memory.threads.list()` to get a list of threads and `client.agent('name').memory.messages.list()` to retrieve messages for a specific thread.
```typescript
const threads = await client.agent("support").memory.threads.list();
const messages = await client
.agent("support")
.memory.messages.list("thread_123", { limit: 20 });
```
--------------------------------
### Basic IP Allowlist Configuration
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/plugins/ip-allowlist/page.mdx
Configure the IP allowlist plugin with a list of allowed IP addresses. By default, it reads common client IP headers.
```typescript
import { betterAgent } from "@better-agent/core";
import { ipAllowlist } from "@better-agent/plugins";
export const app = betterAgent({
agents: [supportAgent],
plugins: [
ipAllowlist({
allow: ["203.0.113.10"],
}),
],
});
```
--------------------------------
### Define Agent with Dynamic Tools Based on Context
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/tools/page.mdx
An agent's `tools` can be a function that dynamically selects tools based on request context, such as user role. This example adds delete and config tools only for admin users.
```typescript
const agent = defineAgent({
name: "assistant",
model: openai("gpt-5.5"),
instruction: "You help users manage their workspace.",
contextSchema: z.object({
role: z.enum(["member", "admin"]),
}),
tools: (ctx) => {
const base = [readTool, searchTool];
if (ctx.role === "admin") {
base.push(deleteTool, configTool);
}
return base;
},
});
```
--------------------------------
### Configure Output Schema Options
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/structured-output/page.mdx
Configure optional name and description for the output schema. These can be passed to the provider to give more context about the expected output structure.
```typescript
output: {
name: "ticket_classification",
description: "Classify the support ticket.",
schema: z.object({
category: z.enum(["bug", "feature", "question"]),
summary: z.string(),
}),
}
```
--------------------------------
### Plugin for Tenant Context Management
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/plugins/page.mdx
This plugin demonstrates how to use the `onStep` hook to modify messages within the agent's context. It prepends system information, such as the run ID, to the existing messages before a step is executed.
```typescript
const tenantContext = definePlugin({
id: "tenant-context",
onStep: async (ctx) => {
ctx.updateMessages((messages) => [
{
role: "system",
content: `Run id: ${ctx.runId}`,
},
...messages,
]);
},
});
```
--------------------------------
### Create In-Memory Storage
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/memory/page.mdx
Create an in-memory storage adapter for local development and testing using `createInMemoryStorage`.
```typescript
import { createInMemoryStorage } from "@better-agent/core";
const storage = createInMemoryStorage();
```
--------------------------------
### Runtime Provider Options
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/gemini/page.mdx
Pass provider-specific options, like Gemini's thinking budget, at runtime.
```typescript
await app.agent("support").run({
messages,
providerOptions: {
google: {
thinkingConfig: { thinkingBudget: 1024 },
},
},
});
```
--------------------------------
### Define Agent with GitHub MCP Tools
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/mcp/page.mdx
Create an agent that can access tools from a GitHub MCP server. This snippet demonstrates setting up the `mcpTools` for an HTTP transport and defining an agent that uses these tools.
```typescript
import { betterAgent, defineAgent } from "@better-agent/core";
import { mcpTools } from "@better-agent/core/mcp";
import { openai } from "@better-agent/openai";
const githubTools = mcpTools({
servers: {
github: {
transport: {
type: "http",
url: "https://api.githubcopilot.com/mcp",
},
},
},
});
const devAgent = defineAgent({
name: "dev",
model: openai("gpt-5.5"),
instruction: "You help with development tasks.",
tools: githubTools,
});
export const app = betterAgent({ agents: [devAgent] });
```
--------------------------------
### Approving or Rejecting Server Tool Calls
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/nextjs/page.mdx
Render UI for server tools awaiting approval using `pendingToolApprovals`. Allows users to approve or reject tool calls.
```tsx
function Approvals({ agent }: { agent: ReturnType }) {
return (
<>
{agent.pendingToolApprovals.map((approval) => (
{approval.toolName}
))}
>
);
}
```
--------------------------------
### Implementing a Workspace Guard Plugin
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/plugins/page.mdx
This snippet shows how to create a plugin that acts as a guard, running before app requests. It checks for a workspace ID in the headers and authorization to determine if the request should proceed or be denied.
```typescript
const workspaceGuard = definePlugin({
id: "workspace-guard",
guards: [
async ({ request, auth }) => {
const workspaceId = request.headers.get("x-workspace-id");
if (!auth || !workspaceId) {
return new Response("Unauthorized", { status: 401 });
}
const allowed = await canAccessWorkspace(auth, workspaceId);
return allowed ? null : new Response("Forbidden", { status: 403 });
},
],
});
```
--------------------------------
### Agent with Request-Aware Instruction
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/concepts/agent/page.mdx
Configures an agent with an instruction function that dynamically adapts based on request context. Requires a context schema to be defined.
```typescript
const agent = defineAgent({
name: "support",
model: openai("gpt-5.5"),
instruction: (context) =>
`You are a support agent for ${context.company}. Speak ${context.language}.`,
contextSchema: z.object({
company: z.string(),
language: z.string(),
}),
});
```
--------------------------------
### Generate Prisma Schema with Better Agent Models
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/database/prisma/page.mdx
Generate the Prisma schema, including Better Agent's models, for a specified database provider.
```bash
npx @better-agent/prisma generate --provider postgresql
```
--------------------------------
### Define Agent with Hosted Tools
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/openai/page.mdx
Configure an agent to use OpenAI's hosted web search tool. Specify parameters like searchContextSize for the tool's behavior.
```typescript
const agent = defineAgent({
name: "researcher",
model: openai("gpt-5.5"),
tools: [
openai.tools.webSearch({ searchContextSize: "medium" }),
],
});
```
--------------------------------
### Configure OpenAI Provider Options at Runtime
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/providers/openai/page.mdx
Pass specific OpenAI provider options, like reasoningEffort, during agent execution. This allows for dynamic adjustment of model behavior per run.
```typescript
await app.agent("support").run({
messages,
providerOptions: {
openai: {
reasoningEffort: "medium",
},
},
});
```
--------------------------------
### Next.js Route Handler for Better Agent
Source: https://github.com/better-agent/better-agent/blob/main/docs/app/docs/integrations/nextjs/page.mdx
Create a catch-all route to handle all incoming requests and forward them to the Better Agent handler.
```typescript
// app/api/agents/[...path]/route.ts
import app from "@/lib/better-agent/server";
export const dynamic = "force-dynamic";
const handle = (request: Request) => app.handler(request);
export const GET = handle;
export const POST = handle;
export const PUT = handle;
export const PATCH = handle;
export const DELETE = handle;
export const OPTIONS = handle;
export const HEAD = handle;
```