From f19adea10d3398c08386665f4382d3172b03bb1a Mon Sep 17 00:00:00 2001 From: 777genius Date: Wed, 29 Apr 2026 11:01:59 +0300 Subject: [PATCH] docs: add openclaw integration guide --- docs/team-management/README.md | 32 +- .../openclaw-agent-teams-integration.md | 811 ++++++++++++++++++ 2 files changed, 834 insertions(+), 9 deletions(-) create mode 100644 docs/team-management/openclaw-agent-teams-integration.md diff --git a/docs/team-management/README.md b/docs/team-management/README.md index c320774b..587c378b 100644 --- a/docs/team-management/README.md +++ b/docs/team-management/README.md @@ -12,41 +12,48 @@ ## Документация -| Файл | Содержание | -|------|-----------| -| [research-inbox.md](./research-inbox.md) | Формат inbox-файлов, race conditions, atomic write, доставка сообщений | -| [research-tasks.md](./research-tasks.md) | Формат task-файлов, .lock, .highwatermark, конкурентный доступ | -| [research-messaging.md](./research-messaging.md) | Сравнение подходов (inbox vs SDK vs CLI), почему выбрали inbox | -| [kanban-design.md](./kanban-design.md) | Kanban flow, колонки, review mechanism, kanban-state.json | -| [implementation.md](./implementation.md) | Техплан: файлы, шаги, verification | -| [research-worktrees.md](./research-worktrees.md) | Git worktrees + teams, запуск Claude процессов из UI (Phase 2) | -| [task-queue-derived-agenda-plan.md](./task-queue-derived-agenda-plan.md) | Подробный rollout-plan по разделению queue/inventory, derived actionOwner и phased agenda/delta sync | +| Файл | Содержание | +| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| [research-inbox.md](./research-inbox.md) | Формат inbox-файлов, race conditions, atomic write, доставка сообщений | +| [research-tasks.md](./research-tasks.md) | Формат task-файлов, .lock, .highwatermark, конкурентный доступ | +| [research-messaging.md](./research-messaging.md) | Сравнение подходов (inbox vs SDK vs CLI), почему выбрали inbox | +| [kanban-design.md](./kanban-design.md) | Kanban flow, колонки, review mechanism, kanban-state.json | +| [implementation.md](./implementation.md) | Техплан: файлы, шаги, verification | +| [openclaw-agent-teams-integration.md](./openclaw-agent-teams-integration.md) | How to connect OpenClaw or another outside AI through Agent Teams MCP and REST control API | +| [research-worktrees.md](./research-worktrees.md) | Git worktrees + teams, запуск Claude процессов из UI (Phase 2) | +| [task-queue-derived-agenda-plan.md](./task-queue-derived-agenda-plan.md) | Подробный rollout-plan по разделению queue/inventory, derived actionOwner и phased agenda/delta sync | ## Ключевые решения ⚠️ `docs/iterations/*` - это исторические planning notes. Они полезны для контекста, но не являются source-of-truth для текущего поведения продукта. Актуальный контракт review flow описан в этом файле и в [kanban-design.md](./kanban-design.md). ### 1. Messaging: Inbox-файлы + Единственный способ общаться с **запущенными** тиммейтами. SDK и CLI создают новые сессии, а не подключаются к существующим. Подробности: [research-messaging.md](./research-messaging.md) ### 1.1 Roster source: members.meta.json + inboxes + - `config.json` не используется как полный реестр участников (он может содержать только team-lead и служебные поля CLI). - Источник метаданных участников (role/color/agentType): `members.meta.json`. - Источник runtime-состава и адресации сообщений: `inboxes/{member}.json`. ### 2. Kanban Storage: Собственный файл + Kanban-позиция (REVIEW, APPROVED) хранится в `kanban-state.json`, а не в task metadata. Причина: metadata может быть перезаписан агентом при TaskUpdate. Подробности: [kanban-design.md](./kanban-design.md) ### 3. Review Flow: Approve / Request Changes + - Есть ревьюверы в команде → автоматическое назначение через inbox - Юзер также может вручную одобрить задачу напрямую из `DONE` без отдельного захода в `REVIEW` - Нет ревьюверов → ручное ревью юзером (Approve / Request Changes в UI) - При Request Changes → юзер описывает проблему (опционально) → задача возвращается owner'у в `pending` с `needsFix` ### 4. Atomic Write + Все записи через tmp + rename для предотвращения corrupted JSON. ### 5. Sender Identity + Отправляем `from: "user"`. Fallback на `from: "team-lead"` если не работает. ## Финальные решения после ревью @@ -54,16 +61,19 @@ Kanban-позиция (REVIEW, APPROVED) хранится в `kanban-state.json` По итогам 3 раундов ревью (13 экспертов) приняты следующие решения: ### Inbox: Atomic write + messageId verify + - Atomic write (tmp + rename) предотвращает corrupted JSON - После записи читаем файл обратно и проверяем наличие нашего `messageId` - Полный CAS/retry-цикл — не нужен на MVP: проверка при следующем read достаточна - Риск race condition с агентом реален, но вероятность низкая ### Kanban: kanban-state.json с безопасным GC + - GC устаревших записей kanban-state выполняется ТОЛЬКО ПОСЛЕ полной загрузки tasks - Иначе при startup возможна race condition: GC удаляет запись до того как task-файл прочитан ### Review Flow: Approve / Request Changes + - Кнопки переименованы: **Approve** (вместо OK) и **Request Changes** (вместо Error) - Комментарий при Request Changes — опционален - Manual UI допускает два valid path: @@ -73,10 +83,12 @@ Kanban-позиция (REVIEW, APPROVED) хранится в `kanban-state.json` - `reviewHistory` и round-robin балансировка → Phase 2, не MVP ### Members: полный список через union + - `union(config members + inbox filenames + task owners)` — единственный способ получить полный список - `owner` в task-файлах — опционален (агент может не иметь owner до назначения) ### Graceful Degradation + - `try/catch` везде в TeamDataService — при ошибке чтения возвращаем безопасные дефолты - 3 состояния участника: `ACTIVE` / `IDLE` / `TERMINATED` - `ACTIVE`: idle < 5 минут @@ -84,6 +96,7 @@ Kanban-позиция (REVIEW, APPROVED) хранится в `kanban-state.json` - `TERMINATED`: получен `shutdown_response` с `approve: true` ### @dnd-kit and review transitions + - Переходы между review-колонками делаются через card actions в UI - `@dnd-kit` сейчас используется в первую очередь для перестановки задач внутри колонки - Phase 2: полноценный D&D через `@dnd-kit` @@ -113,5 +126,6 @@ Kanban-позиция (REVIEW, APPROVED) хранится в `kanban-state.json` ``` **ВАЖНО**: + - `config.json` не является source-of-truth для полного roster. - Полный roster для UI формируется как `members.meta.json + inbox filenames (+ lead из config)`. diff --git a/docs/team-management/openclaw-agent-teams-integration.md b/docs/team-management/openclaw-agent-teams-integration.md new file mode 100644 index 00000000..a2c4b77e --- /dev/null +++ b/docs/team-management/openclaw-agent-teams-integration.md @@ -0,0 +1,811 @@ +# OpenClaw Integration With Agent Teams + +**Status:** Local-first integration guide +**Audience:** OpenClaw or any external AI client that can call MCP tools or local HTTP APIs +**Primary use case:** Let an outside AI create, inspect, launch, and coordinate Agent Teams for complex work and cross-checking + +## 1. Short Answer + +Yes, this is feasible. + +The integration has two layers: + +1. **Agent Teams Desktop App HTTP control API** + - Runs locally on the same machine as the desktop app. + - Defaults to `http://127.0.0.1:3456`. + - Exposes REST endpoints for teams and runtime lifecycle. + +2. **`agent-teams-mcp` stdio MCP server** + - Does not listen on a port. + - Is started by each MCP client as a normal child process. + - Forwards runtime/team operations to the local HTTP control API. + +For OpenClaw, the preferred path is: + +```text +OpenClaw -> stdio MCP process: agent-teams-mcp -> local Agent Teams HTTP API -> Desktop runtime +``` + +Direct REST is also possible: + +```text +OpenClaw -> http://127.0.0.1:3456/api/... -> Desktop runtime +``` + +## 2. Important Architecture Notes + +### 2.1 Multiple MCP Processes Are Expected + +It is safe for multiple agents and OpenClaw to each start their own `agent-teams-mcp` process. + +This works because `agent-teams-mcp` uses **stdio transport**: + +- it does not bind a TCP port; +- it does not own team state; +- it does not create a separate control plane; +- it reads/writes through the shared Agent Teams runtime and shared Claude data directory. + +Example: + +```text +Agent 1 MCP process \ +Agent 2 MCP process -> Agent Teams Desktop HTTP API -> shared teams/tasks/runtime +OpenClaw MCP process/ +``` + +The MCP processes are many. The control plane is one. + +### 2.2 The MCP Server Has No URL + +Do not look for an MCP URL. + +`agent-teams-mcp` is launched by the MCP client: + +```text +client starts process -> client speaks JSON-RPC over stdin/stdout +``` + +The URL belongs to the desktop app HTTP control API, not to MCP. + +### 2.3 The HTTP Control API Is Localhost Only + +The desktop HTTP server binds to `127.0.0.1` by default. + +Default base URL: + +```text +http://127.0.0.1:3456 +``` + +If port `3456` is busy, the app tries the next ports. + +The current URL is published to: + +```text +~/.claude/team-control-api.json +``` + +Example: + +```json +{ + "baseUrl": "http://127.0.0.1:3456", + "pid": 12345, + "updatedAt": "2026-04-29T10:00:00.000Z" +} +``` + +### 2.4 Remote OpenClaw Needs a Tunnel + +If OpenClaw runs on the same Mac as the desktop app, no tunnel is needed. + +If OpenClaw runs on another server, it cannot directly reach `127.0.0.1` on the Mac. Use one of: + +- SSH tunnel; +- reverse tunnel; +- VPN; +- a future authenticated remote control endpoint. + +Do not expose the local HTTP API to the public internet without authentication and transport security. + +## 3. Prerequisites + +1. Agent Teams desktop app is running. +2. HTTP server is enabled in Agent Teams settings. +3. OpenClaw runs on the same machine, or has a secure tunnel to the machine. +4. Node.js 20+ is available if OpenClaw will launch the MCP server from source or build output. + +To confirm the HTTP control API is available: + +```bash +cat ~/.claude/team-control-api.json +curl -s http://127.0.0.1:3456/api/teams +``` + +If the app selected a different port, use the `baseUrl` from `team-control-api.json`. + +## 4. Recommended Integration: MCP + +Use MCP if OpenClaw supports external MCP servers. MCP gives OpenClaw a tool surface instead of forcing it to hand-roll REST calls. + +### 4.1 Dev Workspace MCP Config + +When running from this repository: + +```json +{ + "mcpServers": { + "agent-teams": { + "command": "pnpm", + "args": ["--dir", "/Users/belief/dev/projects/claude/claude_team/mcp-server", "dev"], + "env": { + "AGENT_TEAMS_MCP_CLAUDE_DIR": "/Users/belief/.claude", + "CLAUDE_TEAM_CONTROL_URL": "http://127.0.0.1:3456" + } + } + } +} +``` + +Notes: + +- Adjust the paths for the user's machine. +- `AGENT_TEAMS_MCP_CLAUDE_DIR` tells MCP which Claude data directory to use. +- `CLAUDE_TEAM_CONTROL_URL` is optional if `~/.claude/team-control-api.json` exists, but it is useful for explicit setup. +- If the HTTP server is on another port, update `CLAUDE_TEAM_CONTROL_URL`. + +### 4.2 Built MCP Config + +For a built MCP server: + +```bash +pnpm --filter agent-teams-mcp build +``` + +Then configure OpenClaw like: + +```json +{ + "mcpServers": { + "agent-teams": { + "command": "node", + "args": ["/Users/belief/dev/projects/claude/claude_team/mcp-server/dist/index.js"], + "env": { + "AGENT_TEAMS_MCP_CLAUDE_DIR": "/Users/belief/.claude", + "CLAUDE_TEAM_CONTROL_URL": "http://127.0.0.1:3456" + } + } + } +} +``` + +### 4.3 Packaged App Config + +In a packaged app, the app resolves its bundled MCP entrypoint internally for teams it launches. For an external client like OpenClaw, give it either: + +- the packaged `agent-teams-mcp/dist/index.js` path, if available; +- or a separately installed copy of `agent-teams-mcp`; +- or a dev checkout path while testing. + +The MCP client still starts it as a stdio process. + +## 5. MCP Tool Flow Examples + +The exact UI for tool calls depends on OpenClaw, but the calls are conceptually: + +### 5.1 List Teams + +Tool: + +```text +team_list +``` + +Arguments: + +```json +{ + "controlUrl": "http://127.0.0.1:3456" +} +``` + +`controlUrl` can be omitted if `~/.claude/team-control-api.json` is available. + +### 5.2 Create a Draft Team + +Tool: + +```text +team_create +``` + +Arguments: + +```json +{ + "teamName": "openclaw-review", + "displayName": "OpenClaw Review", + "description": "Team used by OpenClaw to cross-check complex work", + "cwd": "/Users/belief/dev/projects/example-project", + "providerId": "codex", + "providerBackendId": "codex-native", + "model": "gpt-5.4", + "effort": "high", + "fastMode": "inherit", + "limitContext": true, + "skipPermissions": false, + "members": [ + { + "name": "reviewer", + "role": "Reviewer", + "workflow": "Review OpenClaw's work for bugs, missing tests, incorrect assumptions, and integration risks.", + "providerId": "codex", + "providerBackendId": "codex-native", + "model": "gpt-5.4", + "effort": "high", + "fastMode": "inherit" + }, + { + "name": "critic", + "role": "Critical reviewer", + "workflow": "Look for edge cases, concurrency issues, unsafe assumptions, and architectural regressions.", + "providerId": "anthropic", + "model": "claude-opus-4-6", + "effort": "high" + } + ] +} +``` + +This creates a **draft** team. It does not launch the runtime yet. + +### 5.3 Inspect a Team + +Tool: + +```text +team_get +``` + +Arguments: + +```json +{ + "teamName": "openclaw-review" +} +``` + +For a draft team, the response includes draft/saved request data. For a launched/configured team, it returns the team snapshot. + +### 5.4 Launch a Team + +Tool: + +```text +team_launch +``` + +Arguments: + +```json +{ + "teamName": "openclaw-review", + "cwd": "/Users/belief/dev/projects/example-project", + "prompt": "Cross-check OpenClaw's latest changes. Focus on regressions, missing tests, and risky assumptions. Report actionable findings.", + "waitForReady": true, + "waitTimeoutMs": 180000 +} +``` + +`team_launch` works for: + +- a draft team created by `team_create`; +- an existing configured team already known to Agent Teams. + +### 5.5 Stop a Team + +Tool: + +```text +team_stop +``` + +Arguments: + +```json +{ + "teamName": "openclaw-review", + "waitForStop": true +} +``` + +## 6. Suggested OpenClaw Policy + +OpenClaw can use Agent Teams only for work that benefits from parallel review or specialized team behavior. + +Suggested routing: + +1. For small edits, OpenClaw works alone. +2. For risky changes, OpenClaw calls `team_create` if the review team does not exist. +3. OpenClaw calls `team_launch` with a focused review prompt. +4. OpenClaw waits for team readiness. +5. OpenClaw uses the existing MCP board/message tools to create tasks or collect results, if needed. +6. OpenClaw treats Agent Teams feedback as review input, not as automatically trusted output. + +Example instruction for OpenClaw: + +```text +When the task is complex, high-risk, or needs cross-checking, use the agent-teams MCP server. + +Prefer reusing an existing team named "openclaw-review". +If it does not exist, create it with team_create. +Launch it with team_launch and a focused review prompt. +Use team_get to inspect team state. +Do not create duplicate teams with the same purpose. +Do not expose the local control API outside localhost unless the user explicitly configured a secure tunnel. +``` + +## 7. Direct REST API Integration + +Use REST if OpenClaw cannot use MCP, or if you want a very small integration without MCP tool registration. + +Base URL: + +```text +http://127.0.0.1:3456 +``` + +Discover the current base URL: + +```bash +cat ~/.claude/team-control-api.json +``` + +### 7.1 REST Endpoint Summary + +| Method | Path | Purpose | +| ------ | -------------------------------- | --------------------------------- | +| `GET` | `/api/teams` | List teams | +| `POST` | `/api/teams` | Create a draft team configuration | +| `GET` | `/api/teams/:teamName` | Get a draft or configured team | +| `POST` | `/api/teams/:teamName/launch` | Launch a draft or configured team | +| `POST` | `/api/teams/:teamName/stop` | Stop a running team | +| `GET` | `/api/teams/:teamName/runtime` | Get runtime state for one team | +| `GET` | `/api/teams/provisioning/:runId` | Poll launch/provisioning status | +| `GET` | `/api/teams/runtime/alive` | List alive team runtime states | + +Advanced OpenCode runtime bridge endpoints also exist: + +| Method | Path | +| ------ | --------------------------------------------------------- | +| `POST` | `/api/teams/:teamName/opencode/runtime/bootstrap-checkin` | +| `POST` | `/api/teams/:teamName/opencode/runtime/deliver-message` | +| `POST` | `/api/teams/:teamName/opencode/runtime/task-event` | +| `POST` | `/api/teams/:teamName/opencode/runtime/heartbeat` | + +Most OpenClaw integrations should not need the OpenCode runtime bridge endpoints. + +### 7.2 List Teams + +```bash +curl -s http://127.0.0.1:3456/api/teams | jq . +``` + +### 7.3 Create a Draft Team + +```bash +curl -s \ + -X POST http://127.0.0.1:3456/api/teams \ + -H 'content-type: application/json' \ + -d '{ + "teamName": "openclaw-review", + "displayName": "OpenClaw Review", + "description": "Team used by OpenClaw to cross-check complex work", + "cwd": "/Users/belief/dev/projects/example-project", + "providerId": "codex", + "providerBackendId": "codex-native", + "model": "gpt-5.4", + "effort": "high", + "fastMode": "inherit", + "limitContext": true, + "skipPermissions": false, + "members": [ + { + "name": "reviewer", + "role": "Reviewer", + "workflow": "Review OpenClaw work for correctness, regressions, and missing tests.", + "providerId": "codex", + "providerBackendId": "codex-native", + "model": "gpt-5.4", + "effort": "high" + } + ] + }' | jq . +``` + +Expected response: + +```json +{ + "teamName": "openclaw-review" +} +``` + +### 7.4 Get a Draft or Existing Team + +```bash +curl -s http://127.0.0.1:3456/api/teams/openclaw-review | jq . +``` + +Draft response shape: + +```json +{ + "teamName": "openclaw-review", + "pendingCreate": true, + "savedRequest": { + "teamName": "openclaw-review", + "cwd": "/Users/belief/dev/projects/example-project", + "members": [] + } +} +``` + +Configured team response shape is the normal Agent Teams team data snapshot. + +### 7.5 Launch a Team + +```bash +curl -s \ + -X POST http://127.0.0.1:3456/api/teams/openclaw-review/launch \ + -H 'content-type: application/json' \ + -d '{ + "cwd": "/Users/belief/dev/projects/example-project", + "prompt": "Cross-check OpenClaw latest work. Focus on bugs, missing tests, and architectural risks.", + "providerId": "codex", + "providerBackendId": "codex-native", + "model": "gpt-5.4", + "effort": "high", + "fastMode": "inherit", + "limitContext": true, + "skipPermissions": false + }' | jq . +``` + +Expected response: + +```json +{ + "runId": "..." +} +``` + +### 7.6 Poll Launch Status + +```bash +RUN_ID="paste-run-id-here" +curl -s "http://127.0.0.1:3456/api/teams/provisioning/$RUN_ID" | jq . +``` + +Ready states: + +- `ready` +- `failed` +- `disconnected` +- `cancelled` + +A successful launch reaches: + +```json +{ + "state": "ready" +} +``` + +### 7.7 Get Runtime State + +```bash +curl -s http://127.0.0.1:3456/api/teams/openclaw-review/runtime | jq . +``` + +### 7.8 Stop a Team + +```bash +curl -s \ + -X POST http://127.0.0.1:3456/api/teams/openclaw-review/stop \ + -H 'content-type: application/json' \ + -d '{}' | jq . +``` + +## 8. JavaScript REST Client Example + +This is a minimal OpenClaw-side helper. + +```js +import fs from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; + +async function getAgentTeamsBaseUrl() { + if (process.env.CLAUDE_TEAM_CONTROL_URL) { + return process.env.CLAUDE_TEAM_CONTROL_URL; + } + + const statePath = path.join(os.homedir(), '.claude', 'team-control-api.json'); + const raw = await fs.readFile(statePath, 'utf8'); + const parsed = JSON.parse(raw); + if (!parsed.baseUrl) { + throw new Error('team-control-api.json does not contain baseUrl'); + } + return parsed.baseUrl; +} + +async function requestJson(pathname, options = {}) { + const baseUrl = await getAgentTeamsBaseUrl(); + const response = await fetch(`${baseUrl}${pathname}`, { + method: options.method ?? 'GET', + headers: { + accept: 'application/json', + ...(options.body ? { 'content-type': 'application/json' } : {}), + }, + ...(options.body ? { body: JSON.stringify(options.body) } : {}), + }); + + const payload = await response.json().catch(() => null); + if (!response.ok) { + throw new Error(payload?.error || `${response.status} ${response.statusText}`); + } + return payload; +} + +export async function ensureReviewTeam() { + const teamName = 'openclaw-review'; + + try { + return await requestJson(`/api/teams/${teamName}`); + } catch (error) { + if (!String(error.message).includes('not found')) { + throw error; + } + } + + await requestJson('/api/teams', { + method: 'POST', + body: { + teamName, + displayName: 'OpenClaw Review', + cwd: process.cwd(), + providerId: 'codex', + providerBackendId: 'codex-native', + model: 'gpt-5.4', + effort: 'high', + members: [ + { + name: 'reviewer', + role: 'Reviewer', + workflow: 'Cross-check OpenClaw work for bugs, missing tests, and risky assumptions.', + providerId: 'codex', + providerBackendId: 'codex-native', + model: 'gpt-5.4', + effort: 'high', + }, + ], + }, + }); + + return requestJson(`/api/teams/${teamName}`); +} + +export async function launchReviewTeam(prompt) { + const teamName = 'openclaw-review'; + await ensureReviewTeam(); + const launch = await requestJson(`/api/teams/${teamName}/launch`, { + method: 'POST', + body: { + cwd: process.cwd(), + prompt, + providerId: 'codex', + providerBackendId: 'codex-native', + model: 'gpt-5.4', + effort: 'high', + skipPermissions: false, + }, + }); + return launch; +} +``` + +## 9. Validation and Error Behavior + +### 9.1 Team Names + +Team names must be kebab-case: + +```text +[a-z0-9-], max 64 chars +``` + +Good: + +```text +openclaw-review +repo-audit-1 +security-check +``` + +Bad: + +```text +OpenClaw Review +openclaw_review +review team +``` + +### 9.2 Member Names + +Member names are validated by Agent Teams. + +Avoid reserved names: + +- `user` +- `team-lead` + +Use simple names: + +```text +reviewer +critic +tester +architect +``` + +### 9.3 Common HTTP Status Codes + +| Status | Meaning | +| ------ | ------------------------------------------------------------------- | +| `400` | Invalid request payload | +| `404` | Team or run id not found | +| `409` | Conflict, for example team already exists or stale runtime evidence | +| `501` | Team control service is not available in this mode | +| `500` | Unexpected server/runtime error | + +## 10. Recommended Choice + +### Option A: MCP-first integration + +Confidence: `9/10`. Reliability: `8/10`. Complexity: `4/10`. Roughly `20-60 LOC` of OpenClaw config/glue. + +Use this when OpenClaw supports MCP. It is the cleanest integration because OpenClaw sees tools like `team_create`, `team_get`, and `team_launch`. + +Pros: + +- idiomatic for AI clients; +- no custom HTTP client needed; +- multiple MCP processes are safe; +- automatically uses the same team/task tool surface that Agent Teams already gives agents. + +Cons: + +- OpenClaw must support stdio MCP servers; +- debugging involves MCP logs plus desktop logs. + +### Option B: REST-first integration + +Confidence: `8/10`. Reliability: `7/10`. Complexity: `5/10`. Roughly `80-180 LOC` of OpenClaw code. + +Use this when OpenClaw does not support MCP or when you want direct lifecycle control. + +Pros: + +- easy to call from any language; +- simple to debug with curl; +- no MCP client integration needed. + +Cons: + +- only exposes HTTP routes currently implemented; +- OpenClaw must implement retries/polling; +- task/message/board workflows are richer through MCP. + +### Option C: Hybrid MCP + REST + +Confidence: `8/10`. Reliability: `8/10`. Complexity: `7/10`. Roughly `120-260 LOC`. + +Use MCP for normal AI tool calls and REST for health checks, diagnostics, or non-agent automation. + +Pros: + +- best operational visibility; +- can recover from MCP-client-specific issues; +- useful for dashboards or service wrappers. + +Cons: + +- more moving parts; +- more integration surface to test. + +Recommended starting point: **Option A, MCP-first**. + +## 11. Troubleshooting + +### MCP tool says the control API is unavailable + +Check: + +```bash +cat ~/.claude/team-control-api.json +curl -s http://127.0.0.1:3456/api/teams +``` + +Fix: + +- start the Agent Teams desktop app; +- enable the HTTP server in settings; +- pass `CLAUDE_TEAM_CONTROL_URL` explicitly in OpenClaw MCP config. + +### OpenClaw starts MCP, but tool calls fail + +Possible causes: + +- wrong `AGENT_TEAMS_MCP_CLAUDE_DIR`; +- desktop app is using a different Claude root; +- HTTP server is disabled; +- port changed because `3456` was busy; +- OpenClaw runs on another machine without a tunnel. + +### `team_create` returns conflict + +The team already exists. Use `team_get` and either reuse it or choose a new name. + +### `team_launch` hangs or times out + +Check provisioning status: + +```bash +curl -s http://127.0.0.1:3456/api/teams/provisioning/ | jq . +``` + +Possible causes: + +- model/provider unavailable; +- runtime auth missing; +- working directory is invalid; +- app-side provisioning failed; +- team is already in a conflicting runtime state. + +### Remote OpenClaw cannot connect + +This is expected if it is not on the same machine. The API is local-only by default. + +Use an SSH tunnel, for example: + +```bash +ssh -N -L 3456:127.0.0.1:3456 user@mac-mini-host +``` + +Then OpenClaw can use: + +```text +http://127.0.0.1:3456 +``` + +from its own machine if the tunnel is established there. + +## 12. Security Notes + +- The current control API is intended for local use. +- It should not be bound to public interfaces without authentication. +- Prefer SSH tunnels for remote access. +- Treat access to the control API as access to team runtime control. +- Do not share `~/.claude` with untrusted processes. + +## 13. Summary for the Original Request + +The requested integration is realistic: + +- OpenClaw can call Agent Teams through MCP. +- OpenClaw can also call the local REST API directly. +- Each agent/OpenClaw can run its own stdio MCP process. +- Those MCP processes do not conflict because they do not bind ports. +- The single shared control point is the Agent Teams desktop HTTP API. +- For local Mac mini usage, this is the right initial architecture.