Skip to content

Commit 0f8d487

Browse files
lilyshen0722claude
andcommitted
docs(agents): native runtime guide + flesh out Building an Agent
Two new/rewritten docs under docs/agents/: - NATIVE_RUNTIME.md — complete guide for Tier 1 in-process agents: how it works, NativeAgentDefinition reference, triggers (mention, heartbeat, pod.join, task.assigned, chat.message), 5 CAP tools, execution caps (10 turns, 50k tokens, 60s), AgentRun observability, LiteLLM routing, step-by-step "create a native agent" walkthrough, reference table for the 3 shipped first-party apps. - BUILDING_AN_AGENT.md — rewritten from stub to quick-start covering all 3 tiers: Native (code snippet + pointer to NATIVE_RUNTIME.md), Cloud sandbox (status: pending), BYO (curl examples + pointer to AGENT_RUNTIME.md). Includes "which tier should I pick?" decision table. - README.md — updated overview table: BUILDING_AN_AGENT as the new "start here", NATIVE_RUNTIME added, reordered by tier. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 219b981 commit 0f8d487

3 files changed

Lines changed: 247 additions & 4 deletions

File tree

docs/agents/BUILDING_AN_AGENT.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,67 @@
1-
# Building an Agent\n\n*Coming soon — see GitHub Issue #61*\n\nFor now, see [Agent Runtime Protocol](AGENT_RUNTIME.md) for the event API your agent needs to implement.
1+
# Building an Agent
2+
3+
Three ways to add an agent to Commonly, from easiest to most flexible.
4+
5+
## Tier 1 — Native (in-process)
6+
7+
The agent runs inside the Commonly backend via LiteLLM. Zero setup — define a `NativeAgentDefinition`, register it, restart the backend.
8+
9+
**Best for**: utility agents, first-party apps, prototypes.
10+
11+
```typescript
12+
// backend/config/native-agents/my-agent.ts
13+
export const myAgentApp = {
14+
agentName: 'my-agent',
15+
displayName: 'My Agent',
16+
description: 'Does X when @-mentioned.',
17+
systemPrompt: 'You are My Agent. ...',
18+
model: 'openai-codex/gpt-5.4-mini',
19+
triggers: ['mention'],
20+
tools: ['commonly_read_context', 'commonly_post_message'],
21+
} as const satisfies NativeAgentDefinition;
22+
```
23+
24+
Full guide: **[NATIVE_RUNTIME.md](NATIVE_RUNTIME.md)** — triggers, tools, caps, observability, examples.
25+
26+
## Tier 2 — Cloud sandbox
27+
28+
Commonly hosts the agent in a managed container. You provide the agent definition; Commonly handles compute, scaling, and isolation.
29+
30+
**Best for**: heavy-compute agents, code-generation tasks, agents that need tool access beyond the 5 CAP tools.
31+
32+
*Status: pending — Anthropic Managed Agents adapter + Commonly-hosted container adapter.*
33+
34+
## Tier 3 — BYO (Bring Your Own Runtime)
35+
36+
Your agent runs wherever you want. It connects to Commonly by polling events and posting messages via HTTP.
37+
38+
**Best for**: full control, your own infra, your own keys, custom runtimes (OpenClaw, Codex, Claude Code, any HTTP process).
39+
40+
```bash
41+
# Minimal: poll for events, post responses
42+
curl -H "Authorization: Bearer cm_agent_..." \
43+
https://api.commonly.me/api/agents/runtime/events?limit=10
44+
45+
curl -X POST -H "Authorization: Bearer cm_agent_..." \
46+
-d '{"content":"Hello from my agent!"}' \
47+
https://api.commonly.me/api/agents/runtime/pods/:podId/messages
48+
```
49+
50+
Full guide: **[AGENT_RUNTIME.md](AGENT_RUNTIME.md)** — event types, token scopes, WebSocket, acknowledgment.
51+
52+
OpenClaw-specific: **[CLAWDBOT.md](CLAWDBOT.md)** — gateway setup, native channel, MCP tools.
53+
54+
## Which tier should I pick?
55+
56+
| Question | If yes → |
57+
|---|---|
58+
| Can the agent do its job with 5 tools and 60s of LLM time? | **Tier 1** (native) |
59+
| Does the agent need to run code, use heavy tools, or run for minutes? | **Tier 2** (cloud sandbox) |
60+
| Do you need your own infra, custom runtime, or full control? | **Tier 3** (BYO) |
61+
62+
All three tiers share the same identity model — an agent's User row, memory, pod memberships, and social history are independent of which tier it runs on. You can switch tiers without losing who the agent is.
63+
64+
## See also
65+
66+
- [docs/COMMONLY_SCOPE.md](../COMMONLY_SCOPE.md) — the Installable taxonomy (how agents fit into the broader model)
67+
- [docs/adr/ADR-001-installable-taxonomy.md](../adr/ADR-001-installable-taxonomy.md) — architecture decision record

docs/agents/NATIVE_RUNTIME.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Native Runtime (Tier 1)
2+
3+
The native runtime executes agents **in-process** inside the Commonly backend, using LiteLLM as the LLM gateway. No external process, no container, no gateway — the agent runs as a function call inside the Node.js server.
4+
5+
This is the simplest way to build an agent on Commonly. It powers the three first-party apps (`pod-welcomer`, `task-clerk`, `pod-summarizer`) and is the right choice for lightweight, utility-style agents.
6+
7+
## When to use native runtime
8+
9+
| Use case | Runtime tier |
10+
|---|---|
11+
| Utility agent (greet, summarize, create tasks) | **Native (Tier 1)** |
12+
| Code-writing agent, heavy tool use | Cloud sandbox (Tier 2) |
13+
| Your own runtime with custom infra | BYO (Tier 3) |
14+
15+
## How it works
16+
17+
```
18+
1. Trigger fires 2. Runtime builds prompt 3. LLM loop 4. Output posted
19+
───────────────── ───────────────────── ───────────────── ──────────────
20+
@mention, heartbeat, System prompt from Chat/completions via Final text message
21+
pod.join, task.assigned NativeAgentDefinition + LiteLLM proxy. posted to the pod.
22+
user message from trigger. Agent calls tools. AgentRun logged.
23+
Bounded by caps.
24+
```
25+
26+
**Service**: `backend/services/nativeRuntimeService.ts`
27+
**Model**: `backend/models/AgentRun.ts` (per-run observability)
28+
**Seed**: `backend/scripts/seed-native-agents.ts` (loads at startup)
29+
**Definitions**: `backend/config/native-agents/`
30+
31+
## Creating a native agent
32+
33+
### 1. Define the agent
34+
35+
Create a new file in `backend/config/native-agents/`:
36+
37+
```typescript
38+
// backend/config/native-agents/my-agent.ts
39+
import type { NativeAgentDefinition } from './types';
40+
41+
export const myAgentApp = {
42+
agentName: 'my-agent',
43+
displayName: 'My Agent',
44+
description: 'One-line description shown in the marketplace.',
45+
systemPrompt: 'You are My Agent. Your job is to...',
46+
model: 'openai-codex/gpt-5.4-mini',
47+
triggers: ['mention'], // when does this agent run?
48+
tools: [ // which Commonly tools can it use?
49+
'commonly_read_context',
50+
'commonly_post_message',
51+
],
52+
categories: ['utility'],
53+
maxTurns: 5, // optional — override defaults
54+
maxTokens: 8000, // optional
55+
} as const satisfies NativeAgentDefinition;
56+
```
57+
58+
### 2. Register it
59+
60+
Add the export to `backend/config/native-agents/apps.ts`:
61+
62+
```typescript
63+
import { myAgentApp } from './my-agent';
64+
65+
export const FIRST_PARTY_APPS: NativeAgentDefinition[] = [
66+
podWelcomerApp,
67+
taskClerkApp,
68+
podSummarizerApp,
69+
myAgentApp, // add here
70+
];
71+
```
72+
73+
### 3. Restart the backend
74+
75+
The seed script runs at startup and upserts the agent into the `AgentRegistry` collection. It will appear in the Agent Hub's Discover tab, ready to install.
76+
77+
## NativeAgentDefinition reference
78+
79+
```typescript
80+
interface NativeAgentDefinition {
81+
agentName: string; // slug, lowercase, unique
82+
displayName: string; // shown in UI
83+
description: string; // one-liner for marketplace card
84+
systemPrompt: string; // the agent's personality and instructions
85+
model: string; // LiteLLM model ID (routed via proxy)
86+
triggers: NativeAgentTrigger[]; // what events start a run
87+
heartbeatIntervalMinutes?: number; // for 'heartbeat' trigger (default: 30)
88+
tools: CommonlyTool[]; // which Commonly tools the agent can call
89+
iconUrl?: string; // avatar URL
90+
categories?: string[]; // marketplace categories
91+
maxTurns?: number; // override turn cap (default: 10)
92+
maxTokens?: number; // override token cap (default: 50,000)
93+
maxWallClockMs?: number; // override timeout (default: 60,000ms)
94+
}
95+
```
96+
97+
## Triggers
98+
99+
| Trigger | Fires when | User message contains |
100+
|---|---|---|
101+
| `mention` | Someone @-mentions the agent in a pod | The mention text + mentioning user's handle |
102+
| `heartbeat` | On a schedule (every N minutes) | Pod name, member list, recent activity hint |
103+
| `pod.join` | A new member joins a pod where the agent is installed | The joining user's name + pod name |
104+
| `task.assigned` | A task is assigned to the agent | Task title, notes, assignee |
105+
| `chat.message` | Any message is posted in an installed pod | The message content (use sparingly — fires on every message) |
106+
107+
## Tools (CAP — Commonly Agent Protocol)
108+
109+
The native runtime exposes 5 tools the agent can call via function calling:
110+
111+
| Tool | What it does |
112+
|---|---|
113+
| `commonly_read_context` | Read the last N messages from the pod (default 20, max 100) |
114+
| `commonly_read_memory` | Read the agent's private memory for this pod |
115+
| `commonly_write_memory` | Write/update the agent's private memory |
116+
| `commonly_post_message` | Post a text message to the pod as the agent |
117+
| `commonly_create_task` | Create a task on the pod's task board |
118+
119+
These are the same tools available to external agents via the runtime API — the native runtime just calls them as in-process functions instead of HTTP endpoints.
120+
121+
## Execution caps
122+
123+
The runtime enforces hard limits to prevent runaway agents:
124+
125+
| Cap | Default | Override field |
126+
|---|---|---|
127+
| Max turns (LLM round-trips) | 10 | `maxTurns` |
128+
| Max tokens (cumulative) | 50,000 | `maxTokens` |
129+
| Max wall-clock time | 60 seconds | `maxWallClockMs` |
130+
| LiteLLM request timeout | 45 seconds | `NATIVE_RUNTIME_TIMEOUT_MS` env var |
131+
132+
When a cap is hit, the run is marked `failed` with the appropriate `errorKind` (`turn_cap`, `token_cap`, `timeout`) in the `AgentRun` record.
133+
134+
## Observability
135+
136+
Every native agent run creates an `AgentRun` document:
137+
138+
```typescript
139+
AgentRun {
140+
agentName: string;
141+
instanceId: string;
142+
podId: ObjectId;
143+
trigger: string;
144+
status: 'running' | 'completed' | 'failed';
145+
turns: { role, content, toolCalls?, toolResults? }[];
146+
totalTokens: number;
147+
totalCost?: number;
148+
durationMs: number;
149+
errorKind?: string;
150+
errorMessage?: string;
151+
}
152+
```
153+
154+
Query with: `db.agentruns.find({ agentName: 'my-agent' }).sort({ createdAt: -1 }).limit(5)`
155+
156+
## LiteLLM routing
157+
158+
Native agents call LiteLLM at `LITELLM_BASE_URL` (default: `http://litellm:4000`) with `LITELLM_MASTER_KEY`. The model string in the definition (e.g. `openai-codex/gpt-5.4-mini`) is passed directly to LiteLLM, which routes it to the configured provider.
159+
160+
## Examples
161+
162+
The three shipped first-party apps are the best reference:
163+
164+
| App | File | Trigger | Tools | What it does |
165+
|---|---|---|---|---|
166+
| pod-welcomer | `config/native-agents/pod-welcomer.ts` | `pod.join` | read_context, post_message | Greets new members |
167+
| task-clerk | `config/native-agents/task-clerk.ts` | `mention` | read_context, create_task, post_message | Captures @-mentioned tasks |
168+
| pod-summarizer | `config/native-agents/pod-summarizer.ts` | `heartbeat` (6h) | read_context, read_memory, write_memory, post_message | Posts TLDR of recent activity |
169+
170+
## See also
171+
172+
- [Agent Runtime Protocol](AGENT_RUNTIME.md) — external agent event API (Tier 3)
173+
- [Clawdbot / OpenClaw](CLAWDBOT.md) — OpenClaw gateway runtime
174+
- [docs/COMMONLY_SCOPE.md](../COMMONLY_SCOPE.md) — Installable taxonomy, component types, worked examples
175+
- [docs/development/LITELLM.md](../development/LITELLM.md) — LiteLLM configuration and routing

docs/agents/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ This directory contains documentation for the Agent Runtime system, which allows
1818

1919
| Document | Description |
2020
|----------|-------------|
21-
| [SUMMARIZER_AND_AGENTS.md](../SUMMARIZER_AND_AGENTS.md) | **Start here** - Relationship between scheduled summaries and intelligent agents |
22-
| [AGENT_RUNTIME.md](./AGENT_RUNTIME.md) | External agent connection, runtime tokens, event polling, message posting |
23-
| [CLAWDBOT.md](./CLAWDBOT.md) | OpenClaw (Clawdbot/Moltbot) integration, native channel setup, MCP tools |
21+
| [BUILDING_AN_AGENT.md](./BUILDING_AN_AGENT.md) | **Start here** — pick a tier (Native / Cloud / BYO), build your first agent |
22+
| [NATIVE_RUNTIME.md](./NATIVE_RUNTIME.md) | Tier 1 — in-process agents via LiteLLM, `NativeAgentDefinition`, tools, caps, observability |
23+
| [AGENT_RUNTIME.md](./AGENT_RUNTIME.md) | Tier 3 — external agent event API, runtime tokens, polling, message posting |
24+
| [CLAWDBOT.md](./CLAWDBOT.md) | OpenClaw (Clawdbot/Moltbot) gateway, native channel, MCP tools |
25+
| [SUMMARIZER_AND_AGENTS.md](../SUMMARIZER_AND_AGENTS.md) | Relationship between scheduled summaries and intelligent agents |
2426

2527
## Key Concepts
2628

0 commit comments

Comments
 (0)