Skip to content

Quickstart

From an installed CLI to a live local agent service: scaffold an agent, run it, add a typed tool, connect channels, and put the agent on a clock.

This guide takes you from an installed CLI to a live local agent service.

Prerequisites

  • Node >= 22.19 (node --version).
  • FastAgent CLI: npm i -g @fastagent-sh/fastagent.

Model credentials come in step 2 — after the agent exists, because fastagent login stores them per project.

List available model specs with:

fastagent models

1. Create an agent

fastagent init my-agent
cd my-agent

The default scaffold is a self-iterating agent — it is files, and it can edit its own definition (persona.md and skills are re-read every turn). The agent lands in fastagent/; the directory around it is its WORKSPACE — what it works on, and where its AGENTS.md is read from:

my-agent/                              # the workspace — the agent's cwd, untouched by init
└── fastagent/                         # the agent
    ├── persona.md                     # its identity — how to improve yourself
    ├── skills/writing-great-skills/   # the example skill: how to author skills well
    ├── tools/fetch-url.ts             # an example code tool
    ├── fastagent.config.mjs
    ├── package.json
    ├── .secrets/.env.example          # secrets live here, never committed
    └── .gitignore

persona.md teaches the agent to capture durable improvements as new skills; writing-great-skills (vendored from mattpocock/skills) is the guide it consults to write them. No AGENTS.md is scaffolded — that file is project context the agent reads (yours, or a host repo’s), not its identity. Add more skills with fastagent add skill <owner/repo/path>. For a agent with no code tool or dependencies (persona.md + the skill + config only):

fastagent init my-agent --minimal

2. Inspect it

fastagent info

info is read-only. It prints the model, persona, context files (AGENTS.md), skills, discovered tools, channels, diagnostics, and session path without starting a server.

Initializing inside an existing project? Same command, same result: init puts the WHOLE agent into ./fastagent/ — zero writes elsewhere, so the project’s build and the agent’s surface never sweep each other, and the repo’s own AGENTS.md is read as project context. A fastagent.config.* file identifies the agent; fastagent/ is only the default directory name.

The repository IS the agent? (A standalone agent repo, or a monorepo package.) fastagent init . --flat puts the same shape at the root instead. Existing files are kept untouched, and the agent’s workspace is its own directory, so its tools operate on its own definition. Want a different directory name? fastagent init . --agent-dir bot — the fastagent.config.* inside is what makes a directory an agent, never its name.

A fresh agent presets no model. On the first fastagent dev (or start / invoke) in a terminal, FastAgent shows the full model catalog — models whose provider already has credentials (a stored login, or a provider API key in your env/.env) come first, annotated with the source; picking one that needs auth runs the login flow right there — and writes your pick back to fastagent.config.mjs. Credentials are stored per project (<agent dir>/.secrets/auth.json, no global fallback), so a login from another directory is invisible here. To set the model non-interactively (or in CI/deploy, where there is no prompt):

fastagent dev --model provider/model-id
FASTAGENT_MODEL=provider/model-id fastagent dev
# or edit fastagent.config.mjs

3. Run locally

fastagent dev

dev assembles the agent and serves it on :8787. persona.md/AGENTS.md/skills/ edits go live on the next turn; code edits (tools/, channels/, config) restart the worker. The default channel is POST /invoke.

Send one turn:

curl -N -X POST localhost:8787/invoke \
  -H 'content-type: application/json' \
  -d '{"session":"s1","text":"Summarize https://example.com in two bullets"}'

The response is Server-Sent Events. Events include text, optional thinking, tool events, and exactly one terminal completed or failed.

data: {"type":"tool_started","id":"tool-1","name":"fetch-url","args":{"url":"https://example.com"}}

data: {"type":"tool_ended","id":"tool-1","isError":false,"content":{"details":{"url":"https://example.com/","text":"Example Domain …"}}}

data: {"type":"completed"}

Reuse the same session value to continue a conversation. Local sessions persist under <state root>/sessions (default fastagent/.state/sessions), so a dev restart keeps conversation history.

4. Try authoring loops

Open the same assembled agent in pi’s interactive TUI:

fastagent chat

Run one agent turn without a server:

fastagent invoke "Summarize persona.md in one sentence"

Run one tool without a model:

fastagent tool fetch-url '{"url":"https://example.com"}'

5. Add a tool

Tools are files in tools/. The filename is the tool name.

// tools/reverse.ts
import { defineTool, z } from "@fastagent-sh/fastagent";

export default defineTool({
  description: "Reverse a string.",
  input: z.object({ text: z.string() }),
  async execute({ text }) {
    return { reversed: [...text].reverse().join("") };
  },
});

Test it directly:

fastagent tool reverse '{"text":"hello"}'

Mention the tool in persona.md so the model knows when to use it. fastagent dev reloads on save.

6. Serve without watch

fastagent start

start uses the same assembly as dev, but does not watch files. There is no build step: copy the agent to a host with Node >= 22.19, install dependencies, and run fastagent start.

For deployments, point both machinery roots at durable storage: the state root (sessions and channel state — Telegram’s durable turn replay lives there too) and the secrets dir (the agent’s .env and the auth.json an OAuth refresh rotates on the box):

FASTAGENT_STATE_DIR=/data/.state FASTAGENT_SECRETS_DIR=/data/.secrets fastagent start

(FASTAGENT_SESSIONS_DIR / --sessions-dir override just the sessions path; they do not move channel state, and neither knob moves auth.json.)

7. Add channels

Add a first-party channel:

fastagent add github
fastagent add telegram
fastagent add slack
fastagent add feishu     # 飞书 (open.feishu.cn)
fastagent add lark       # Lark international

Then run locally with a public tunnel for webhook testing:

fastagent dev --tunnel

Read Channels for the channel model, GitHub channel for GitHub webhooks, Telegram channel for Telegram bots, Slack channel for Slack apps, and Feishu channel (Lark compatibility) for Feishu and Lark bots.

8. Run on a clock

Channels turn external events into invocations; schedules do the same for the clock — firing the agent on a cron: a daily digest, a periodic check. Drop a file in schedules/ (mirroring tools/), named by its filename:

// schedules/daily-digest.ts
import { defineSchedule } from "@fastagent-sh/fastagent";

export default defineSchedule({
  cron: "0 9 * * *",
  tz: "America/New_York",
  prompt: "Summarize yesterday's activity and send it to the team Telegram.",
});

The prompt must say where output goes — the scheduler only fires the agent; delivery is a send tool’s job. fastagent add telegram scaffolds one (tools/telegram-send.ts sends a message or a file); and because a scheduled turn runs outside any chat, the agent has no chat context — put the target chat id in the prompt (“…send it to Telegram chat -100123456”). Test it immediately (without waiting for the cron, and without touching the real fire state):

fastagent fire daily-digest

On resident hosts, the cron fires while dev/start is serving; keep the process running. AgentCore ingress instead uses EventBridge and supports scale-to-zero. fastagent schedule history <name> answers “did last night’s run silently fail?”, and fastagent schedule list shows the selected local state’s pending work. Agents can also schedule themselves (a built-in wake tool — “check the deploy in 10 minutes”) — opt in with selfSchedule: true in fastagent.config.*. See the CLI reference and API reference.

Where next

  • Agent development guide — responsibilities, TypeScript, verification, and host-specific operation.
  • Embedding — use FastAgent as a library inside your own app.
  • Channels — webhook and bot adapters.
  • Deploy — ship the directory to Fly, Railway, AWS Bedrock AgentCore, or any Docker host.
  • Agent Handler SPEC — the event stream contract.
  • Core design — maintainer architecture notes.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close