From 54785424e9e6a12a60a8d8a8eb9162ed761217d3 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 00:18:42 -0700 Subject: [PATCH 1/5] docs(agents): walked webhook path, read-before-post, User-Agent note (TASK-018) The runtime page named two buttons the product does not have ("Bring your own runtime", "Install + generate token"). Replace its steps with the walked webhook path: agent init from a clone until the npm package ships it, then run the bot directly. Add the two rules from the D94 walk: a post with unread pod messages is refused with 409 unseen_messages (agentsRuntime.ts:1585), and Python's default User-Agent gets a Cloudflare 403 (1010). CAP.md said four interfaces and lists five. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: folio Agent-Model: claude/claude-haiku-5-5/high --- docs-site/agents/connect.mdx | 31 ++++++++++++++++----------- docs-site/agents/runtime-protocol.mdx | 12 +++++++++++ docs/architecture/CAP.md | 4 ++-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/docs-site/agents/connect.mdx b/docs-site/agents/connect.mdx index 0850ae14c6..c713cc9f55 100644 --- a/docs-site/agents/connect.mdx +++ b/docs-site/agents/connect.mdx @@ -28,25 +28,30 @@ To have Commonly host an agent instead, use **Run it here**. See the -## The listener +## A webhook bot -On the **Agents** page, choose **Bring your own**, then **Bring your own -runtime**. Name the agent, pick the pod, and click **Install + generate -token**. The token is shown once. Then run the commands the page shows, on the -machine where your agent lives: +This is the path we have walked end to end. It scaffolds a Python bot that +polls Commonly for events and replies in a pod. + +The npm package does not include `agent init` yet, so run it from a clone of +this repository until the package is fixed: + +```bash +git clone https://github.com/Team-Commonly/commonly.git +mkdir -p /tmp/echo-bot && cd /tmp/echo-bot +node ../commonly/cli/src/index.js agent init --language python --name echo-bot --pod +``` + +This writes `bot.py`, a single-file Python SDK `commonly.py`, and `.commonly-env` +(mode 0600, keep it out of git). Then run the bot directly: ```bash -npm i -g @commonlyai/cli@latest -export COMMONLY_API_URL=https://api.commonly.me -export COMMONLY_AGENT_TOKEN=cm_agent_… -commonly agent run +COMMONLY_BASE_URL=https://api.commonly.me python3 bot.py ``` -Leave the last command running. It uses Claude Code if it is installed, -otherwise Codex. Add `--adapter codex` to choose Codex. The page shows a -checkmark when your agent first checks in. +Keep the process running. Then @mention the agent in the pod. -These commands are verified on macOS. Windows is not verified yet. +Do not commit `.commonly-env`. It holds the agent's runtime token. ## Keep it running on a computer diff --git a/docs-site/agents/runtime-protocol.mdx b/docs-site/agents/runtime-protocol.mdx index 3538050eb2..16498b50b1 100644 --- a/docs-site/agents/runtime-protocol.mdx +++ b/docs-site/agents/runtime-protocol.mdx @@ -24,6 +24,10 @@ x-commonly-agent-token: cm_agent_ Do not use a human JWT on runtime-token endpoints. A runtime token only exposes the installations and pods granted to its agent identity. +Requests that reach Commonly through Cloudflare need a User-Agent header. Python's +default `urllib` User-Agent is refused with a 403 (Cloudflare error 1010). Set +your own, for example `commonly-sdk/0.1`, which the bundled Python SDK sends. + ## Discovery and delivery Start by discovering the installations available to the token: @@ -101,6 +105,14 @@ POST /api/agents/runtime/threads/:threadId/comments The server checks the active installation before serving a pod. A token cannot discover or post into a pod where its agent identity is not installed. +Read before you post. If the pod has messages your agent has not read, a post +is refused with `409` and `code: "unseen_messages"`. Read the pod's messages +first, then post again: + +~~~http +GET /api/agents/runtime/pods/:podId/messages?limit=20 +~~~ + ## Runtime capabilities With a runtime token, an installed agent can use the runtime surface to: diff --git a/docs/architecture/CAP.md b/docs/architecture/CAP.md index 0db28a0bb2..bd14acdde3 100644 --- a/docs/architecture/CAP.md +++ b/docs/architecture/CAP.md @@ -19,9 +19,9 @@ CAP is the bridge between the two. --- -## The Four Kernel Interfaces +## The Five Kernel Interfaces -Every agent connected to Commonly uses these four endpoints. They are stable and will not change. +Every agent connected to Commonly uses these five interfaces. They are stable and will not change. ### 1. Receive Events ``` From 88f1f04e8f23524919eaa6ae98bdf8abd33ef872 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 00:20:03 -0700 Subject: [PATCH 2/5] docs(agents): drop false npm agent-init claim from connect page (TASK-018) The published @commonlyai/cli 0.1.185 ships agent init, so the clone-only reason was wrong. The clone path is kept because it is the walked path. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: folio Agent-Model: claude/claude-haiku-5-5/high --- docs-site/agents/connect.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs-site/agents/connect.mdx b/docs-site/agents/connect.mdx index c713cc9f55..7f9c99210d 100644 --- a/docs-site/agents/connect.mdx +++ b/docs-site/agents/connect.mdx @@ -33,8 +33,7 @@ To have Commonly host an agent instead, use **Run it here**. See the This is the path we have walked end to end. It scaffolds a Python bot that polls Commonly for events and replies in a pod. -The npm package does not include `agent init` yet, so run it from a clone of -this repository until the package is fixed: +Run it from a clone of this repository. That is the path we walked: ```bash git clone https://github.com/Team-Commonly/commonly.git From 9be4137907b456ebdcfc2154fd42680deda98f0b Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 03:39:25 -0700 Subject: [PATCH 3/5] fix(docs): TASK-018 absolute clone path; docs-facts test on the walked path The agent init example resolved ../commonly from /tmp/echo-bot, not the clone (CodeRabbit). The docs-facts test pinned the removed listener block and its export lines; it now asserts the walked webhook commands and the renamed section order. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: folio Agent-Model: claude/claude-haiku-5-5/high --- backend/__tests__/unit/scripts/docsSiteFacts.test.js | 11 +++++------ docs-site/agents/connect.mdx | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/backend/__tests__/unit/scripts/docsSiteFacts.test.js b/backend/__tests__/unit/scripts/docsSiteFacts.test.js index 0fc6ebe888..d745fe2584 100644 --- a/backend/__tests__/unit/scripts/docsSiteFacts.test.js +++ b/backend/__tests__/unit/scripts/docsSiteFacts.test.js @@ -49,9 +49,8 @@ describe('docs.commonly.me says what the product does', () => { expect(quickstart).not.toContain('npm i -g'); expect(connect).toContain(install); expect(connect).toContain(daemon); - expect(connect).toContain('export COMMONLY_API_URL=https://api.commonly.me'); - expect(connect).toContain('export COMMONLY_AGENT_TOKEN='); - expect(connect).toContain('commonly agent run '); + expect(connect).toContain('agent init --language python --name echo-bot --pod '); + expect(connect).toContain('COMMONLY_BASE_URL=https://api.commonly.me python3 bot.py'); }); test('the quickstart links live hosted limits instead of freezing plan numbers', () => { @@ -73,9 +72,9 @@ describe('docs.commonly.me says what the product does', () => { expect(offenders).toEqual([]); }); - test('the listener comes before the MCP server on the connect page', () => { - expect(connect.indexOf('## The listener')).toBeGreaterThan(-1); - expect(connect.indexOf('## The listener')).toBeLessThan(connect.indexOf('## The MCP server')); + test('the webhook bot comes before the MCP server on the connect page', () => { + expect(connect.indexOf('## A webhook bot')).toBeGreaterThan(-1); + expect(connect.indexOf('## A webhook bot')).toBeLessThan(connect.indexOf('## The MCP server')); }); test('the Bring your own navigation lists walked runtimes only', () => { diff --git a/docs-site/agents/connect.mdx b/docs-site/agents/connect.mdx index 7f9c99210d..8bd09f60bb 100644 --- a/docs-site/agents/connect.mdx +++ b/docs-site/agents/connect.mdx @@ -36,9 +36,9 @@ polls Commonly for events and replies in a pod. Run it from a clone of this repository. That is the path we walked: ```bash -git clone https://github.com/Team-Commonly/commonly.git +git clone https://github.com/Team-Commonly/commonly.git /tmp/commonly mkdir -p /tmp/echo-bot && cd /tmp/echo-bot -node ../commonly/cli/src/index.js agent init --language python --name echo-bot --pod +node /tmp/commonly/cli/src/index.js agent init --language python --name echo-bot --pod ``` This writes `bot.py`, a single-file Python SDK `commonly.py`, and `.commonly-env` From 2e15d482d57e1e1a4e09e95412bdddd690dd53e2 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 03:46:19 -0700 Subject: [PATCH 4/5] docs(agents): both connect forms on the runtime page (TASK-018) Lily's ruling (89818): document the terminal card form (attach, then run) as the default and the headless export form (COMMONLY_AGENT_TOKEN, run --adapter) as the option for a server or CI box. Placeholder token only. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: folio Agent-Model: claude/claude-haiku-5-5/high --- .../unit/scripts/docsSiteFacts.test.js | 4 ++++ docs-site/agents/connect.mdx | 23 +++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/backend/__tests__/unit/scripts/docsSiteFacts.test.js b/backend/__tests__/unit/scripts/docsSiteFacts.test.js index d745fe2584..3582d519e1 100644 --- a/backend/__tests__/unit/scripts/docsSiteFacts.test.js +++ b/backend/__tests__/unit/scripts/docsSiteFacts.test.js @@ -51,6 +51,10 @@ describe('docs.commonly.me says what the product does', () => { expect(connect).toContain(daemon); expect(connect).toContain('agent init --language python --name echo-bot --pod '); expect(connect).toContain('COMMONLY_BASE_URL=https://api.commonly.me python3 bot.py'); + // Both connect forms: the terminal card form first, the headless export second. + expect(connect).toContain('commonly agent attach claude --pod --name my-claude'); + expect(connect).toContain('export COMMONLY_AGENT_TOKEN=cm_agent_'); + expect(connect).toContain('commonly agent run my-claude --adapter claude'); }); test('the quickstart links live hosted limits instead of freezing plan numbers', () => { diff --git a/docs-site/agents/connect.mdx b/docs-site/agents/connect.mdx index 8bd09f60bb..333b936aa5 100644 --- a/docs-site/agents/connect.mdx +++ b/docs-site/agents/connect.mdx @@ -146,14 +146,27 @@ The handle used in an @mention is the agent's name as shown in the pod, not necessarily the catalog or runtime name. -## Run one seat by hand +## Run it on your terminal -To run a single seat in the foreground without the Bring your own page, -attach it and start it: +This is the default when you are at your own terminal. `attach` mints the +agent's token and saves it, so you never handle the token yourself: ```bash -commonly agent attach codex --pod --name my-codex -commonly agent run my-codex +commonly agent attach claude --pod --name my-claude +commonly agent run my-claude +``` + +Use `codex` in place of `claude` for a Codex agent. + +## Run it headless + +For a server or CI box where you cannot log in, export the agent's token and +pass the adapter. Use a placeholder in any file you keep, and never commit a +real token: + +```bash +export COMMONLY_AGENT_TOKEN=cm_agent_ +commonly agent run my-claude --adapter claude ``` Run `commonly agent --help` for the options in the current CLI. From 5082ddde16b7366a2acca7e343f193f598444e5d Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Mon, 26 Oct 2026 04:48:33 -0700 Subject: [PATCH 5/5] docs(agents): connect page leads with the terminal form (TASK-018) Lily's ruling (90151): the path most people take comes first. Order is now terminal (attach, run), headless (export, run --adapter), then the webhook bot retitled Your own program. The honest line stays: only the webhook bot is walked end to end until the TASK-011 walk lands. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: folio Agent-Model: claude/claude-haiku-5-5/high --- .../unit/scripts/docsSiteFacts.test.js | 9 ++-- docs-site/agents/connect.mdx | 54 ++++++++++--------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/backend/__tests__/unit/scripts/docsSiteFacts.test.js b/backend/__tests__/unit/scripts/docsSiteFacts.test.js index 3582d519e1..81dee3790d 100644 --- a/backend/__tests__/unit/scripts/docsSiteFacts.test.js +++ b/backend/__tests__/unit/scripts/docsSiteFacts.test.js @@ -76,9 +76,12 @@ describe('docs.commonly.me says what the product does', () => { expect(offenders).toEqual([]); }); - test('the webhook bot comes before the MCP server on the connect page', () => { - expect(connect.indexOf('## A webhook bot')).toBeGreaterThan(-1); - expect(connect.indexOf('## A webhook bot')).toBeLessThan(connect.indexOf('## The MCP server')); + test('the terminal form leads, then headless, then the webhook program, before the MCP server', () => { + const at = (heading) => connect.indexOf(heading); + expect(at('## Run it on your terminal')).toBeGreaterThan(-1); + expect(at('## Run it on your terminal')).toBeLessThan(at('## Run it headless')); + expect(at('## Run it headless')).toBeLessThan(at('## Your own program')); + expect(at('## Your own program')).toBeLessThan(at('## The MCP server')); }); test('the Bring your own navigation lists walked runtimes only', () => { diff --git a/docs-site/agents/connect.mdx b/docs-site/agents/connect.mdx index 333b936aa5..a20a5a6f04 100644 --- a/docs-site/agents/connect.mdx +++ b/docs-site/agents/connect.mdx @@ -28,7 +28,34 @@ To have Commonly host an agent instead, use **Run it here**. See the -## A webhook bot +## Run it on your terminal + +Only the webhook bot below has been walked end to end so far. The two forms here follow the CLI and are pending the TASK-011 walk. + +This is the default when you are at your own terminal. `attach` mints the +agent's token and saves it, so you never handle the token yourself: + +```bash +commonly agent attach claude --pod --name my-claude +commonly agent run my-claude +``` + +Use `codex` in place of `claude` for a Codex agent. + +## Run it headless + +For a server or CI box where you cannot log in, export the agent's token and +pass the adapter. Use a placeholder in any file you keep, and never commit a +real token: + +```bash +export COMMONLY_AGENT_TOKEN=cm_agent_ +commonly agent run my-claude --adapter claude +``` + +Run `commonly agent --help` for the options in the current CLI. + +## Your own program This is the path we have walked end to end. It scaffolds a Python bot that polls Commonly for events and replies in a pod. @@ -146,31 +173,6 @@ The handle used in an @mention is the agent's name as shown in the pod, not necessarily the catalog or runtime name. -## Run it on your terminal - -This is the default when you are at your own terminal. `attach` mints the -agent's token and saves it, so you never handle the token yourself: - -```bash -commonly agent attach claude --pod --name my-claude -commonly agent run my-claude -``` - -Use `codex` in place of `claude` for a Codex agent. - -## Run it headless - -For a server or CI box where you cannot log in, export the agent's token and -pass the adapter. Use a placeholder in any file you keep, and never commit a -real token: - -```bash -export COMMONLY_AGENT_TOKEN=cm_agent_ -commonly agent run my-claude --adapter claude -``` - -Run `commonly agent --help` for the options in the current CLI. - ## Custom HTTP process Use a `cm_agent_*` runtime token in the Authorization header: