Getting Started
Create a project, issue an agent token, download the binary, and run your first conversation.
This guide takes you from zero to a live agent that you can send messages to and stream responses from.
Prefer the terminal over the dashboard? Install the CLI from CLI, then:
bot login
bot projects create "my-app"
bot agents create PROJECT_ID worker
bot runtime install && bot runtime start
bot runtime auth --project PROJECT_ID --agent AGENT_ID
bot runtime send "Hello" --wait 2m
Prerequisites
- A dashboard account with
whitelisted_useroradminaccess (W3 ID sign-in), or a workingbot loginsession (same W3 identity via device flow). - A place to run the runtime binary — your laptop, a server, or a container.
1. Create a project
A project is the unit of organization: it owns a workspace, members, agents, and a usage quota. Create one from Projects → New Project in the dashboard.
Each project gets a workspace folder (for files and an optional AGENTS.md) and
a skills/ folder automatically.
2. Create an agent
Open your project and use Create agent. The agent is a project-scoped record that can be issued tokens. On creation you receive a bootstrap token.
Bootstrap tokens are single-use and expire fast
The bootstrap token expires in 5 minutes and can only be used once to establish the runtime session. It cannot be retrieved later — copy it immediately. You can generate a new one from the agent page if it expires.
3. Download the runtime
From the agent page, download the zip for your platform. The dashboard always
serves the latest GitHub Release and shows its version (for example v0.2.0):
| Platform | Download |
|---|---|
| macOS (universal) | bot-agent-macos-universal-v{version}.zip |
| Linux (x64) | bot-agent-linux-x64-v{version}.zip |
| Windows (x64) | bot-agent-windows-x64-v{version}.zip |
Unzip it. Keep the binary next to lib/ (needed for browser automation):
bot-agent-{platform}-v{version}/
├── bot-agent # or bot-agent-linux-x64 / bot-agent.exe
├── VERSION
└── lib/rebrowser-playwright/...
macOS: clear Gatekeeper quarantine
Browser downloads mark the binary as quarantined. macOS may show “bot-agent is damaged and can’t be opened” — that is Gatekeeper, not a corrupt file. Before first run (folder name includes the version):
xattr -cr bot-agent-macos-universal-v0.2.0
codesign --force --sign - bot-agent-macos-universal-v0.2.0/bot-agent
(Same steps if you downloaded a bare binary instead of a zip.)
4. Run the agent
Pick a home directory for state (SQLite DB, config, logs, browser profiles).
DB_TYPE is required (sqlite or postgres):
export DB_TYPE=sqlite
export BOT_AGENT_API_KEY=your-local-api-key # recommended; protects the local HTTP API
./bot-agent --home /data/my-agent --port 4484 --api-key "$BOT_AGENT_API_KEY"
# Linux zip binary may be named bot-agent-linux-x64
Poll GET /health until 200 { "status": "ok" } before continuing. Spawn,
ports/sockets, and lifecycle details: Deployment.
5. Authenticate (once)
The runtime never holds LLM keys. Instead, it exchanges the bootstrap token from step 2 for a JWT session against the control plane:
curl -X POST http://localhost:4484/auth/session \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BOT_AGENT_API_KEY" \
-d '{"cloudBaseUrl":"https://169.63.180.31.sslip.io","bootstrapToken":"<token>"}'
# → { "signedIn": true, "productId": "...", "deviceId": "...", "entitlements": {...} }
The dashboard's agent page shows a ready-to-copy version of this command with
your cloudBaseUrl pre-filled. The runtime caches the session and refreshes
tokens automatically.
6. Send a message and stream the response
Messaging is asynchronous — POST /messages returns 202 immediately, and
you receive the assistant reply over WebSocket.
// 1. Create a conversation
const conv = await fetch("http://localhost:4484/conversations", {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({
title: "My Assistant",
workspacePath: "/home/me/project",
}),
}).then((r) => r.json());
// 2. Send a message (returns 202 right away)
await fetch(`http://localhost:4484/conversations/${conv.id}/messages`, {
method: "POST",
headers: authHeaders(),
body: JSON.stringify({ content: "Hello, what can you do?" }),
});
// 3. Stream the response
const ws = new WebSocket(
`ws://localhost:4484/conversations/${conv.id}/ws?api_key=${KEY}`,
);
ws.onmessage = (e) => {
const evt = JSON.parse(e.data);
if (evt.type === "message.delta") appendToUi(evt.data.delta); // stream tokens
if (evt.type === "run.completed") markDone();
};
That's a working agent. Call the runtime from your app over HTTP/WebSocket — full surface (cancel, crons, fork, compaction, subagents):
Or skip writing a client: download a ready-made
web chat UI or desktop app from this dashboard
and point it at http://localhost:4484.
Next steps
- Frontend UIs — web and desktop chat clients
- Architecture — runtime loop and tools
- Deployment — spawn as a child process, sockets, browser