# Project layout

An Agent SDK project keeps agent files under `bot/`. Each
file's path determines how Agent SDK loads it.

Existing projects rooted at `agent/` remain supported.

## Folder structure

For the capabilities below, identity comes from the path.

| Path under `bot/` | Resolves to |
| --- | --- |
| `tools/approve_pr.ts` | tool `approve_pr` |
| `mcp-connections/linear.ts` | MCP connection `linear` (model + host) |
| `host-connections/inventory.ts` | Host MCP connection `inventory` (host + `mcp oauth` only) |
| `skills/pr-review.md` | skill `pr-review` |
| `subagents/reviewer/` | subagent `reviewer` |
| `extensions/ci.ts` | extension mount `ci`; its contributions become `ci__<name>` |
| `extensions/notion.ts` | Cursor plugin mount `notion` (`cursorPlugin`); its skills, agents, and MCP servers become `notion__<name>` |
| `channels/drive.ts` | channel `drive`, routes under `/v1/channels/drive` |

The root agent takes its name from `package.json` `name`, falling back
to the directory name. When serving multiple agents, the slug is the
directory name and must match `[A-Za-z0-9][A-Za-z0-9_-]*` (and not the
reserved `v1`, `playground`, or `docs` segments).

## Project tree

Most projects start with this shape.

```text
my-agent/
├── package.json
├── bot/
│   ├── agent.ts               # model and local harness config
│   ├── instructions.md        # always-on system prompt (required)
│   ├── tools/
│   │   └── approve_pr.ts      # one typed tool per file
│   ├── skills/
│   │   └── pr-review.md       # on-demand procedures (SKILL.md convention)
│   ├── mcp-connections/
│   │   └── linear.ts          # tools from external MCP servers
│   ├── host-connections/
│   │   └── inventory.ts       # host-only MCP tools
│   ├── subagents/
│   │   └── reviewer/
│   │       ├── agent.ts
│   │       └── instructions.md
│   ├── channels/
│   │   └── github.ts          # messages and external events
│   └── hooks/
│       └── audit.ts           # observe session events
└── evals/
    └── readiness.eval.ts      # regression cases
```

Evals stay in `evals/` at the project root, as a sibling of `bot/`, never
inside it. See [Evals](/docs/evals.md).

## Folder reference

Each path maps to a capability and a reference page.

| Path under `bot/` | What it is | Reference |
| --- | --- | --- |
| `agent.ts` | `defineAgent({ model?, local? })`; the model defaults to `grok-4.5` with `effort=high`, `fast=true` | [Agent config](/docs/reference/agent-config.md) |
| `instructions.md` | Always-on system prompt, required on the root agent (`.ts` and directory forms exist) | [Instructions](/docs/reference/instructions.md) |
| `tools/<name>.ts` | One typed tool; filename = tool name. `execution: "server"` (in-process, default) or `"agent"` (a script that runs where the agent runs) | [Tools](/docs/reference/tools.md) |
| `skills/*` | SKILL.md-convention procedures, loaded on demand | [Skills](/docs/reference/skills.md) |
| `mcp-connections/<name>.ts` | MCP servers, available to the model, to server tools (`ctx.host.mcp`), and to channel/schedule handlers (`args.host.mcp`) | [MCP connections](/docs/reference/connections.md) |
| `host-connections/<name>.ts` | Privileged MCP servers for `ctx.host.mcp` and `mcp oauth`. The model never sees them. | [MCP connections](/docs/reference/connections.md) |
| `subagents/<id>/` | Child agent directory; `description` required | [Subagents](/docs/reference/subagents.md) |
| `extensions/<ns>.ts` or `extensions/<ns>/` | A mounted extension or Cursor plugin; its contributions become `<ns>__<name>` | [Extensions](/docs/reference/extensions.md) |
| `channels/*.ts` | HTTP surfaces beyond the built-in session API; `slack.ts` and `github.ts` use the platform packs | [Channels](/docs/reference/channels.md) |
| `hooks/*.ts` | Observe-only event subscribers, never fatal | [Hooks](/docs/reference/hooks.md) |
| `artifacts.ts` | `defineArtifacts` kinds, the `tag_artifact` opt-in, and retention | [Artifacts](/docs/reference/artifacts.md) |
| `schedules/*` | Cron-driven runs (UTC, 5-field; never auto-fire under `--dev`) | [Schedules](/docs/reference/schedules.md) |
| `reminders/*.ts` | Named reminder handlers that stay armed across restarts | [Schedules](/docs/reference/schedules.md#reminders) |
| `sandbox/workspace/**` | Seed files copied into each local session workspace | [Sessions](/docs/reference/sessions.md#local-session-workspace) |
| `lib/` | Import-only shared code, never discovered | None |

Discovery rejects a `bot/result.ts` file. To act on a turn's decision, have
the model record it with an authored [tool](/docs/reference/tools.md), then act on it from a
`turn.completed` [hook](/docs/reference/hooks.md).

Evals use project-root paths:

| Project-root path | What it is | Reference |
| --- | --- | --- |
| `evals/evals.config.ts` | Shared eval settings (e.g. `maxConcurrency`); required when evals exist | [Evals](/docs/evals.md) |
| `evals/**/*.eval.ts` | Filesystem evals; case id = path under `evals/` | [Evals](/docs/evals.md) |

Use `bot/lib/` for shared imports. A `.ts` file in one of the listed
discovery folders loads as a definition; unrecognized directories produce
a validation warning.

## Inspect discovery

Run `agent-sdk validate --dir .` and `agent-sdk info --dir .`.
`validate` prints diagnostics, and `serve` refuses to start on
error-severity ones. Warnings print but don't block. `info` lists the discovered
surface, so a missing tool or channel shows up immediately. From
there, check the folder reference: the file is usually in the wrong directory
or has the wrong extension.

```text
agent-sdk validate --dir .    # diagnostics; non-zero exit on errors
agent-sdk info --dir .        # human-readable surface
agent-sdk info --dir . --json # machine-readable project info (same shape as GET /v1/info)
```

## Related

- [Agent config](/docs/reference/agent-config.md): the config at the project root
- [Tools](/docs/reference/tools.md): add typed actions under `tools/`
- [CLI](/docs/reference/cli.md): commands that discover this tree
