# Agent config

`bot/agent.ts` default-exports `defineAgent(config)`, which sets the model
that runs the agent and the defaults for a local run. Every field is optional on
the root agent.

```ts
import { defineAgent } from "@grok/agent-sdk";

export default defineAgent({
  model: {
    id: "grok-4.5",
    params: [
      { id: "effort", value: "high" },
      { id: "fast", value: "true" },
    ],
  }, // optional; this is the default
});
```

## Agent fields

| Field          | Type                                  | Meaning                                                                                                                                                                                         |
| -------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`        | string or `{ id, params }`            | Cursor model for turns. Defaults to `grok-4.5` with `effort=high` and `fast=true`. Subagents omit it to inherit.                                                                                |
| `name`         | string                                | Display name. Defaults to the package or directory name.                                                                                                                                        |
| `description`  | string                                | What the agent is for. Required on subagents, where the parent model reads it to decide when to delegate.                                                                                       |
| `instructions` | string                                | Inline instructions for subagents and generated configs. Prefer `instructions.md`.                                                                                                              |
| `local`        | `{ cwd?, workspaceDir?, sandbox? }`   | Defaults for a local run. See [Local options](https://cursor.com/docs/agent-sdk/reference/agent-config.md#local-options).                                                                       |
| `hosting`      | `{ egressDomains?, secretNames? }`    | The egress allowlist and expected secret names that `agent-sdk deploy` reads. Mounted [extensions](https://cursor.com/docs/agent-sdk/reference/extensions.md#build-an-extension) add their own. |
| `concurrency`  | `{ maxRunningTurns? }`                | Agent-wide limit on concurrent turns. See [Concurrency](https://cursor.com/docs/agent-sdk/reference/agent-config.md#concurrency).                                                               |
| `builtinTools` | `{ reminders? }`                      | Opt-in tools that Agent SDK provides. See [Built-in tools](https://cursor.com/docs/agent-sdk/reference/agent-config.md#built-in-tools).                                                         |
| `tools`        | `ToolName[]`                          | Allowlist of built-in tools. Omit it for the full standard toolset. See [Harness tools](https://cursor.com/docs/agent-sdk/reference/agent-config.md#harness-tools).                             |
| `fs`           | `FileSystem` or `(ctx) => FileSystem` | Custom file tree for the session. `root` is the deprecated name. See [Custom filesystem](https://cursor.com/docs/agent-sdk/reference/agent-config.md#custom-filesystem).                        |
| `skills`       | `false` or `(ctx) => FileSystem`      | Replaces the skills tree mounted at `/agent/skills`, or turns that mount off.                                                                                                                   |

The `persistent` field was removed. Discovery rejects a config that still sets it, and the error is `persistent was removed. Delete it from defineAgent.`, so `validate`, `dev`, and `deploy` fail until you delete the field. A deployment that is already running keeps serving until you stop or delete it.

## Model

Effort and speed are params, not id suffixes, so Agent SDK rejects an id like
`grok-4.5-fast`. Use the object form shown above to set params, or a plain
string when you don't need any:

```ts
model: "composer-2.5",
```

## Local options

`local.workspaceDir` points every session at one shared working directory, for
agents that work inside an existing checkout. It takes precedence over `cwd`,
and a per-send `workspaceDir` wins over both. Sessions share that tree, so one
turn's files are visible to the next.

`local.sandbox` runs the agent inside Cursor's local sandbox. It's off by
default, so shell commands auto-approve and inherit the serve process
environment, including the host's credentials. Turn it on when turns read
untrusted input, such as webhook payloads, PR diffs, or inbound chat. The
sandbox limits the tools themselves, so an injected prompt can't talk the model
past it.

Agent SDK runs the file tools (`read`, `edit`, `delete`, `grep`, `glob`, `ls`)
in the serve process, outside the sandbox. With `local.sandbox` on, they refuse
a path outside the session workspace with `Path is outside the workspace`. With
it off, they can reach any path the serve process can.

### Local cwd

`local.cwd` sets the parent directory for local session workspaces. Each
session uses `<cwd>/<sessionId>` unless a per-send `workspaceDir` overrides it.

Session workspaces are real Cursor project directories, so the local agent reads
`AGENTS.md` and `.cursor` config from every ancestor directory. When you omit
`cwd` and the agent sits inside another git repo, such as a monorepo package,
Agent SDK uses a per-project directory under `~/.cache` instead, so the
enclosing checkout's rules, skills, and MCP servers stay out of the turn. An
agent at its own git root keeps its workspaces inside the project. Point `cwd`
at a checkout only when the agent should inherit that tree.

## Custom filesystem

`fs` is mounted at `/`, and Agent SDK mounts `/tmp` and `/agent/skills` over it. Set `fs` or the deprecated `root`, not both. A tree that already has `/agent/skills` fails session start unless `skills` is `false`.

## Harness tools

Use `tools` to limit which built-in Cursor tools the model can call.
When you set it, the model gets only the tools you list. An empty list turns
off every built-in tool, and new platform tools stay off until you add them.

```ts
export default defineAgent({
  model: "composer-2.5",
  // Read-only triage: no shell, no edits, no subagents.
  tools: ["read", "grep", "glob", "ls"],
});
```

Agent SDK always adds `"mcp"` to a configured allowlist, because the server
tools in `bot/tools/` reach the model over MCP. With `local.sandbox` on, MCP
tool calls fail closed. An enclosing checkout can also add MCP servers, as
[Local cwd](https://cursor.com/docs/agent-sdk/reference/agent-config.md#local-cwd) explains.

Use the Cursor SDK's public tool names, such as `"shell"`, `"read"`,
`"edit"`, `"grep"`, `"glob"`, `"ls"`, and `"task"`. An unknown name fails the
turn with a `ConfigurationError`, and `"SemanticSearch"` or `"semSearch"`
fails validation.

Two names have broader effects:

- `"shell"` also grants shell input. Tools with `execution: "agent"` need it
  to run their scripts, and discovery warns when your allowlist blocks them.
- `"task"` lets the root agent start subagents. Each subagent keeps its own
  toolset.

The allowlist doesn't isolate the serve host, so pair it with `local.sandbox`
for untrusted input.

## Migrate off semantic search

Semantic search is removed, and `agent-sdk validate` reports
`Semantic search has been removed. Use Grep.` while a project still uses it.
[A turn fails or misbehaves](https://cursor.com/docs/agent-sdk/troubleshooting.md#a-turn-fails-or-misbehaves) lists what to
delete and what to use instead.

## Concurrency

`concurrency.maxRunningTurns` caps how many model turns run at once across the agent's sessions. It takes a positive integer up to 200. Omit it for no limit.

When every slot is busy, a new turn queues in arrival order instead of failing. The stream records a `turn.queued` event with the queue
position, `GET /v1/sessions` reports `queued: true`, and the turn starts as
soon as a slot frees.

A queued turn still counts as running. A follow-up preempts it, and a direct
write-effect tool call gets `409 session_busy`.

```ts
export default defineAgent({
  concurrency: { maxRunningTurns: 3 },
});
```

## Built-in tools

`builtinTools` opts into tools that Agent SDK provides. They behave like your
own server tools in turns, direct calls, `info`, and the playground. A tool you
write with the same name wins, with a warning.

`builtinTools: { reminders: true }` adds `reminders_create`, `reminders_list`,
and `reminders_cancel`, bound to the current conversation. A session without a
continuation key can't set reminders. See
[Schedules and reminders](https://cursor.com/docs/agent-sdk/reference/schedules.md#reminders).

## Serve programmatically

`serve(dirOrProject, options)` embeds the server in your own process:

```ts
import { serve } from "@grok/agent-sdk";

const handle = await serve("./my-agent", {
  port: 3000,
});
console.log(`listening on ${handle.url}`);
// handle.callTool(...), handle.dispatchSchedule("heartbeat"),
// handle.createReminder(...), handle.agents, await handle.close()
```

`handle.agents` lists each mount as `{ slug, url, info }`. `handle.project` is
deprecated.

`serve()` takes the same host settings as the [CLI](https://cursor.com/docs/agent-sdk/reference/cli.md) `serve` flags,
plus `discovery` for project-loading options and `mode: "single" | "multi"`.
Pass `apiKey`, or sign in the same way as the CLI, as
[Environment variables](https://cursor.com/docs/agent-sdk/reference/cli.md#environment-variables) describes.

## Inspect a project in tests

`loadProject(dir)` reads one project without serving it. Its `info` matches the
`GET /v1/info` body.

```ts
import { loadProject } from "@grok/agent-sdk";

const { info } = await loadProject("./my-agent", { strict: true });
expect(info.tools.map((t) => t.name)).toContain("inspect_pr");
```

`loadProject` throws `ProjectLoadError` when discovery reports an error, and
`{ strict: true }` makes it throw on a warning too. `error.diagnostics` lists
the findings, and each `path` is relative to the project directory. `serve`
accepts the loaded project or a directory path.

## Related

- [Instructions](https://cursor.com/docs/agent-sdk/reference/instructions.md)
- [Sessions](https://cursor.com/docs/agent-sdk/reference/sessions.md)


---

## Sitemap

[Overview of all docs pages](/llms.txt)
