agent-ecosystem/docs/team-management/openclaw-agent-teams-integration.md

1212 lines
33 KiB
Markdown

# OpenClaw Integration With Agent Teams
- **Status:** local-first integration guide
- **Audience:** OpenClaw or any outside AI client that can run MCP tools or call a local REST API
- **Primary use case:** let an outside AI create, inspect, launch, and cross-check Agent Teams work
- **Recommended first implementation:** MCP-first, REST as a lifecycle/debug fallback
## 1. Executive Summary
Yes, this integration is feasible.
The clean local architecture is:
```text
OpenClaw
starts agent-teams-mcp over stdio
calls Agent Teams desktop HTTP control API
controls shared Agent Teams runtime and shared ~/.claude state
```
There are two integration surfaces:
1. **MCP surface**
- Best fit for an AI agent like OpenClaw.
- OpenClaw starts `agent-teams-mcp` as a child process.
- The MCP server exposes tools such as `team_list`, `team_create`, `team_get`, `team_launch`, `task_create`, `message_send`, `review_request`, and more.
2. **REST control API**
- Best fit for lifecycle automation, health checks, debugging, and simple wrappers.
- Runs inside the Agent Teams desktop app.
- Defaults to `http://127.0.0.1:3456`.
- Currently covers team lifecycle/runtime control. It does not replace the full board/message MCP tool surface.
For the original request - "can OpenClaw call Agent Teams for complex tasks and cross-checking?" - the answer is:
```text
Use MCP for normal AI-to-Agent-Teams interaction.
Use REST for lifecycle/debug or if OpenClaw cannot use MCP yet.
```
## 2. The Mental Model
### 2.1 What Runs Where
```text
Mac mini or local Mac
Agent Teams Desktop App
- owns Electron UI
- owns team runtime process management
- owns local HTTP control API
- writes current control API URL to ~/.claude/team-control-api.json
agent-teams-mcp
- stdio MCP server process
- started by each MCP client that needs it
- does not listen on a port
- forwards lifecycle operations to the desktop HTTP control API
- uses ~/.claude for team/task/message controller state
OpenClaw
- external AI client
- can start agent-teams-mcp as an MCP server
- can optionally call REST directly
```
### 2.2 One Control Plane, Many MCP Processes
Multiple MCP processes are expected and safe.
```text
Agent 1 MCP process \
Agent 2 MCP process -> one Agent Teams desktop HTTP API -> shared teams/tasks/runtime
OpenClaw MCP process/
```
This is safe because `agent-teams-mcp` is a stdio process:
- it does not bind a port;
- it does not own global runtime state;
- it does not create a second app server;
- it uses the shared desktop app control API for lifecycle operations;
- it uses the shared Claude data directory for team/task/message state.
The thing that must be singular is the **desktop control plane**, not the MCP process.
### 2.3 What Can Conflict
MCP processes themselves should not conflict.
Possible conflicts are logical, not port/process conflicts:
- two clients create the same `teamName`;
- two clients launch or stop the same team at the same time;
- two clients edit the same task concurrently;
- one client changes the board while another client is using stale state.
These are normal shared-state coordination issues. They are not caused by multiple MCP servers.
## 3. Recommended Integration Choice
### Option A: MCP-first integration
Scores: 🎯 9/10 🛡️ 8/10 🧠 4/10
Expected OpenClaw changes: roughly `20-80 LOC` plus configuration.
Use this if OpenClaw supports stdio MCP servers.
Why it is the recommended path:
- it matches how AI clients naturally call tools;
- it exposes the richer board/task/message/review surface;
- each OpenClaw run can start its own MCP process safely;
- it avoids writing a custom task/message client against internal files;
- it keeps OpenClaw integration close to the tools Agent Teams already gives team agents.
Use REST only for health checks and debugging in this option.
### Option B: REST-first lifecycle integration
Scores: 🎯 7/10 🛡️ 7/10 🧠 5/10
Expected OpenClaw changes: roughly `80-180 LOC`.
Use this if OpenClaw cannot run MCP yet.
Important limitation:
```text
REST currently covers team lifecycle/runtime control.
It is not the full board/task/message/review control surface.
```
REST can:
- list teams;
- create draft team configs;
- get team snapshots;
- launch teams;
- stop teams;
- poll runtime/provisioning state.
REST should not be treated as the full replacement for task/message MCP tools.
### Option C: Hybrid integration
Scores: 🎯 8/10 🛡️ 8/10 🧠 7/10
Expected OpenClaw changes: roughly `120-260 LOC`.
Use MCP for normal AI tool calls, and REST for operational checks.
Good split:
- MCP: team operations, task creation, messages, reviews, process registry.
- REST: "is the desktop app alive?", "what is the runtime state?", "what is the current run status?"
This is the best long-term shape if OpenClaw needs both agentic workflows and a supervisory dashboard.
## 4. Local Setup Checklist
### 4.1 Start Agent Teams Desktop App
The desktop app must be running. It owns the runtime and local HTTP API.
### 4.2 Enable Browser Access / Server Mode
In the desktop app:
```text
Settings -> Browser Access -> Enable server mode
```
When enabled, the app starts a local Fastify HTTP server.
Default:
```text
http://127.0.0.1:3456
```
If port `3456` is busy, the app tries the next ports.
### 4.3 Discover the Current Control API URL
The desktop app writes the active URL 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"
}
```
Check it:
```bash
cat ~/.claude/team-control-api.json
```
Then verify REST:
```bash
curl -s http://127.0.0.1:3456/api/teams
```
If the file shows a different port, use that `baseUrl`.
### 4.4 Local vs Remote OpenClaw
If OpenClaw runs on the same Mac:
```text
No tunnel needed.
Use http://127.0.0.1:<port>.
```
If OpenClaw runs on another machine:
```text
127.0.0.1 points to the OpenClaw machine, not to the Mac running Agent Teams.
Use an SSH tunnel, reverse tunnel, VPN, or another secure local-network setup.
```
Basic SSH tunnel 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 the machine where the tunnel is open.
## 5. MCP Integration
### 5.1 What OpenClaw Needs To Do
OpenClaw should register `agent-teams-mcp` as a stdio MCP server.
That means OpenClaw starts a process and speaks MCP JSON-RPC over stdin/stdout.
OpenClaw does **not** connect to an MCP URL.
The URL belongs to the desktop HTTP control API and is passed to MCP through:
- `CLAUDE_TEAM_CONTROL_URL`, or
- `~/.claude/team-control-api.json`, or
- per-tool `controlUrl`.
### 5.2 Dev Checkout MCP Config
Use this while testing from the repository checkout:
```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"
}
}
}
}
```
Adjust:
- repo path;
- Claude data directory;
- control URL port.
### 5.3 Built MCP Config
Build:
```bash
pnpm --filter agent-teams-mcp build
```
Configure OpenClaw:
```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"
}
}
}
}
```
### 5.4 If OpenClaw Supports `cwd`
Some MCP clients allow a `cwd` field. If OpenClaw supports it, this is cleaner:
```json
{
"mcpServers": {
"agent-teams": {
"command": "pnpm",
"args": ["dev"],
"cwd": "/Users/belief/dev/projects/claude/claude_team/mcp-server",
"env": {
"AGENT_TEAMS_MCP_CLAUDE_DIR": "/Users/belief/.claude",
"CLAUDE_TEAM_CONTROL_URL": "http://127.0.0.1:3456"
}
}
}
}
```
If OpenClaw does not support `cwd`, use the `pnpm --dir ... dev` form.
### 5.5 MCP URL Discovery Order
For lifecycle tools such as `team_list`, `team_get`, `team_create`, and `team_launch`, the control URL is resolved in this order:
1. tool argument `controlUrl`;
2. `~/.claude/team-control-api.json`;
3. environment variable `CLAUDE_TEAM_CONTROL_URL`.
Passing `CLAUDE_TEAM_CONTROL_URL` is the most explicit OpenClaw setup.
Passing `controlUrl` per tool call is useful for debugging or tunnels.
### 5.6 MCP Tool Surface
Current tool groups:
| Group | Tools |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Team lifecycle | `team_list`, `team_get`, `team_create` |
| Runtime lifecycle | `team_launch`, `team_stop` |
| Task board | `task_create`, `task_create_from_message`, `task_get`, `task_get_comment`, `task_list`, `task_start`, `task_complete`, `task_set_owner`, `task_set_status`, `task_add_comment`, `task_link`, `task_unlink`, `task_set_clarification`, `task_restore`, `task_attach_file`, `task_attach_comment_file`, `task_briefing`, `member_briefing` |
| Lead briefing | `lead_briefing` |
| Review | `review_request`, `review_start`, `review_approve`, `review_request_changes` |
| Messages | `message_send` |
| Cross-team | `cross_team_send`, `cross_team_list_targets`, `cross_team_get_outbox` |
| Kanban | `kanban_get`, `kanban_set_column`, `kanban_clear`, `kanban_list_reviewers`, `kanban_add_reviewer`, `kanban_remove_reviewer` |
| Process registry | `process_register`, `process_list`, `process_stop`, `process_unregister` |
| Runtime bridge | `runtime_bootstrap_checkin`, `runtime_deliver_message`, `runtime_task_event`, `runtime_heartbeat` |
Most OpenClaw integrations need:
```text
team_list
team_get
team_create
team_launch
team_stop
task_create
task_list
task_get
message_send
review_request
review_request_changes
review_approve
```
The `runtime_*` tools are low-level OpenCode runtime bridge tools. Do not use them for ordinary user/team messaging.
## 6. MCP Workflow Examples
The exact call UI depends on OpenClaw. The examples below show the arguments conceptually.
### 6.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` exists and points to the running desktop app.
### 6.2 Get a Team
Tool:
```text
team_get
```
Arguments:
```json
{
"teamName": "openclaw-review"
}
```
For a draft team, the response includes `pendingCreate` and `savedRequest`.
For a configured team, the response is the normal team snapshot.
### 6.3 Create a Draft Review 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 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 config. It does not start the runtime.
Important:
- Put provider/backend/model/fast-mode defaults into `team_create`.
- MCP `team_launch` currently accepts a smaller runtime override shape.
- When launching a draft through MCP, saved draft fields are reused.
### 6.4 Launch the Team
Tool:
```text
team_launch
```
Arguments:
```json
{
"teamName": "openclaw-review",
"cwd": "/Users/belief/dev/projects/example-project",
"prompt": "Cross-check OpenClaw latest work. Focus on bugs, missing tests, and architectural risks. Return concise actionable findings.",
"waitForReady": true,
"waitTimeoutMs": 180000
}
```
`team_launch` works for:
- a draft team created by `team_create`;
- an existing configured team.
Current MCP `team_launch` launch overrides are intentionally smaller than `team_create`:
```text
cwd
prompt
model
effort: low | medium | high
clearContext
skipPermissions
worktree
extraCliArgs
waitForReady
waitTimeoutMs
```
Do not pass `providerId`, `providerBackendId`, `fastMode`, or `limitContext` to MCP `team_launch`.
Put those into `team_create` so the saved draft can be reused at launch time.
If `waitForReady` is true, the tool waits for provisioning to reach `ready` or fail.
### 6.5 Create a Review Task After Launch
Use this if OpenClaw wants the team to track review work on the board.
Tool:
```text
task_create
```
Arguments:
```json
{
"teamName": "openclaw-review",
"subject": "Review OpenClaw latest patch",
"description": "Check correctness, tests, edge cases, and integration risks. Report concrete findings only.",
"owner": "reviewer",
"createdBy": "openclaw",
"startImmediately": true
}
```
`task_create` requires a configured team, so launch the team first.
### 6.6 Send a Message To the Team
Tool:
```text
message_send
```
Arguments:
```json
{
"teamName": "openclaw-review",
"to": "reviewer",
"from": "openclaw",
"text": "Please review the latest changes. Focus on regressions and missing tests.",
"summary": "Review request from OpenClaw"
}
```
Use `message_send` for normal visible messages.
Do not use `runtime_deliver_message` for ordinary OpenClaw-to-team communication.
### 6.7 Stop the Team
Tool:
```text
team_stop
```
Arguments:
```json
{
"teamName": "openclaw-review",
"waitForStop": true
}
```
## 7. Suggested OpenClaw Policy
OpenClaw should not call Agent Teams for every small task. Use it when parallel review or team behavior matters.
Suggested policy:
```text
Use the agent-teams MCP server when the task is complex, high-risk, user-visible, or needs independent cross-checking.
Prefer the existing team "openclaw-review".
Call team_get first.
If it does not exist, call team_create.
Call team_launch with a focused prompt.
If the review should be tracked, create a task with task_create.
Use message_send for visible follow-up messages.
Do not create duplicate teams with the same purpose.
Do not call runtime_* tools unless implementing an OpenCode runtime bridge.
Do not expose the local control API outside localhost without a secure tunnel.
```
Recommended task routing:
1. Small code change: OpenClaw handles it alone.
2. Medium risk: OpenClaw launches `openclaw-review` for cross-checking.
3. High risk: OpenClaw creates explicit review tasks for multiple reviewers.
4. Release/blocking work: OpenClaw uses task/review tools and waits for explicit review outcome.
## 8. Direct REST API Integration
REST is useful when:
- OpenClaw cannot run MCP yet;
- you need a simple health/lifecycle wrapper;
- you are debugging the desktop control API;
- you want a non-agent script to create or launch teams.
REST is **not** currently the full board/message/review surface.
Use MCP for task board and messaging operations.
### 8.1 Base URL
Default:
```text
http://127.0.0.1:3456
```
Discover current:
```bash
cat ~/.claude/team-control-api.json
```
Use:
```bash
BASE_URL="$(
node <<'NODE'
const fs = require('fs');
const path = require('path');
const statePath = path.join(process.env.HOME, '.claude', 'team-control-api.json');
if (fs.existsSync(statePath)) {
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
console.log(state.baseUrl || 'http://127.0.0.1:3456');
} else {
console.log('http://127.0.0.1:3456');
}
NODE
)"
echo "$BASE_URL"
```
Or set manually:
```bash
BASE_URL="http://127.0.0.1:3456"
```
### 8.2 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:
| 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` |
Do not use the OpenCode runtime bridge endpoints for normal OpenClaw user/team messages.
### 8.3 List Teams
```bash
curl -s "$BASE_URL/api/teams" | jq .
```
### 8.4 Create a Draft Team
```bash
curl -s \
-X POST "$BASE_URL/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"
}
```
### 8.5 Get a Draft or Existing Team
```bash
curl -s "$BASE_URL/api/teams/openclaw-review" | jq .
```
Draft shape:
```json
{
"teamName": "openclaw-review",
"pendingCreate": true,
"savedRequest": {
"teamName": "openclaw-review",
"cwd": "/Users/belief/dev/projects/example-project",
"providerId": "codex",
"members": [
{
"name": "reviewer",
"role": "Reviewer"
}
]
}
}
```
Configured teams return the normal Agent Teams team snapshot.
### 8.6 Launch a Team
```bash
curl -s \
-X POST "$BASE_URL/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",
"skipPermissions": false
}' | jq .
```
Expected response:
```json
{
"runId": "..."
}
```
For draft teams, missing launch fields fall back to the saved draft request where supported.
For existing configured teams, the launch payload is the runtime override for this launch.
⚠️ `limitContext` should be set during `team_create` for this integration path.
Do not depend on it as a configured-team REST launch override unless the route parser is extended.
### 8.7 Poll Launch Status
```bash
RUN_ID="paste-run-id-here"
curl -s "$BASE_URL/api/teams/provisioning/$RUN_ID" | jq .
```
Terminal states:
- `ready`
- `failed`
- `disconnected`
- `cancelled`
Successful launch:
```json
{
"state": "ready"
}
```
### 8.8 Get Runtime State
```bash
curl -s "$BASE_URL/api/teams/openclaw-review/runtime" | jq .
```
### 8.9 Stop a Team
```bash
curl -s \
-X POST "$BASE_URL/api/teams/openclaw-review/stop" \
-H 'content-type: application/json' \
-d '{}' | jq .
```
## 9. JavaScript REST Client Example
This is a minimal lifecycle-only helper for OpenClaw.
It does not implement task/message/review operations. Use MCP for those.
```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;
}
async function teamExists(teamName) {
try {
return await requestJson(`/api/teams/${encodeURIComponent(teamName)}`);
} catch (error) {
const message = String(error.message || '').toLowerCase();
if (message.includes('not found')) {
return null;
}
throw error;
}
}
export async function ensureReviewTeam({ cwd = process.cwd() } = {}) {
const teamName = 'openclaw-review';
const existing = await teamExists(teamName);
if (existing) {
return existing;
}
await requestJson('/api/teams', {
method: 'POST',
body: {
teamName,
displayName: 'OpenClaw Review',
description: 'Team used by OpenClaw to cross-check complex work',
cwd,
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'high',
fastMode: 'inherit',
limitContext: true,
skipPermissions: false,
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',
fastMode: 'inherit',
},
],
},
});
return requestJson(`/api/teams/${encodeURIComponent(teamName)}`);
}
export async function launchReviewTeam({ cwd = process.cwd(), prompt }) {
const teamName = 'openclaw-review';
await ensureReviewTeam({ cwd });
const launch = await requestJson(`/api/teams/${encodeURIComponent(teamName)}/launch`, {
method: 'POST',
body: {
cwd,
prompt,
providerId: 'codex',
providerBackendId: 'codex-native',
model: 'gpt-5.4',
effort: 'high',
fastMode: 'inherit',
skipPermissions: false,
},
});
return launch;
}
export async function waitForReady(runId, { timeoutMs = 180000, pollMs = 1000 } = {}) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeoutMs) {
const status = await requestJson(`/api/teams/provisioning/${encodeURIComponent(runId)}`);
if (status.state === 'ready') {
return status;
}
if (['failed', 'disconnected', 'cancelled'].includes(status.state)) {
throw new Error(`Team launch ended in ${status.state}: ${status.error || 'no details'}`);
}
await new Promise((resolve) => setTimeout(resolve, pollMs));
}
throw new Error(`Timed out waiting for run ${runId}`);
}
```
Example use:
```js
const launch = await launchReviewTeam({
cwd: '/Users/belief/dev/projects/example-project',
prompt: 'Cross-check the latest OpenClaw changes. Return concrete bugs and missing tests.',
});
await waitForReady(launch.runId);
```
## 10. Validation Rules
### 10.1 Team Names
Team names must be kebab-case:
```text
lowercase alphanumeric segments separated by single hyphens, max 64 chars
```
Good:
```text
openclaw-review
repo-audit-1
security-check
```
Bad:
```text
OpenClaw Review
openclaw_review
review team
review--team
-review
review-
```
### 10.2 Member Names
Avoid reserved names:
- `user`
- `team-lead`
Good:
```text
reviewer
critic
tester
architect
```
### 10.3 Providers and Runtime Fields
Provider IDs:
```text
anthropic
codex
gemini
opencode
```
Provider backend IDs:
```text
auto
adapter
api
cli-sdk
codex-native
```
Fast mode:
```text
inherit
on
off
```
Effort values are provider-dependent. Common values include:
```text
low
medium
high
```
Codex-oriented create flows may also use values such as:
```text
none
minimal
xhigh
max
```
Use values supported by the selected provider/runtime.
## 11. Error Behavior
Common REST 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 |
Common MCP failures:
| Symptom | Likely cause |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Control API unavailable | Desktop app not running, server mode disabled, wrong `CLAUDE_TEAM_CONTROL_URL`, or wrong `~/.claude` |
| `team_create` conflict | Team already exists |
| `team_launch` timeout | Runtime auth/model/cwd/provisioning issue |
| Task tools fail after `team_create` | Team is still a draft. Launch it first |
| Remote OpenClaw cannot connect | Missing tunnel or wrong host mapping |
## 12. Troubleshooting
### 12.1 Confirm Desktop Control API
```bash
cat ~/.claude/team-control-api.json
curl -s http://127.0.0.1:3456/api/teams | jq .
```
If the file has another port, use that port.
### 12.2 Confirm MCP Starts
From the repo:
```bash
pnpm --dir /Users/belief/dev/projects/claude/claude_team/mcp-server dev
```
This starts the stdio server and waits for MCP JSON-RPC input. It will not print a normal HTTP URL.
In a real OpenClaw setup, OpenClaw starts this process itself.
### 12.3 MCP Starts But Tool Calls Fail
Check:
- `AGENT_TEAMS_MCP_CLAUDE_DIR` points to the same Claude root as the app;
- `CLAUDE_TEAM_CONTROL_URL` points to the app's current local HTTP URL;
- Agent Teams desktop app is running;
- Browser Access / server mode is enabled;
- OpenClaw is on the same machine or has a working tunnel.
### 12.4 `team_create` Says Team Already Exists
Use:
```text
team_get
```
Then reuse the existing team, or pick another `teamName`.
### 12.5 `team_launch` Hangs
With REST, poll:
```bash
curl -s "$BASE_URL/api/teams/provisioning/<runId>" | jq .
```
With MCP, use `waitForReady: true` and a larger `waitTimeoutMs`.
Possible causes:
- model unavailable;
- provider authentication missing;
- invalid working directory;
- provisioning failure;
- already-running/stale runtime state.
### 12.6 Remote OpenClaw Cannot Connect
This is expected without a tunnel.
The desktop API binds to `127.0.0.1`, so a remote process cannot see it directly.
Use SSH tunnel or VPN. Do not publish the control API to a public interface without authentication.
## 13. Security Notes
- Treat the control API as runtime control access.
- Keep it local by default.
- Prefer SSH tunnels for remote use.
- Do not expose it publicly without authentication and transport security.
- Do not share `~/.claude` with untrusted processes.
- Remember that an AI client with this MCP server can create, launch, stop, and coordinate teams.
## 14. What To Tell The User
Use this short explanation:
```text
Yes, this is feasible.
Agent Teams can expose a local control API from the desktop app, and an outside AI like OpenClaw can access it through the agent-teams MCP server.
OpenClaw would start agent-teams-mcp as a stdio MCP server. That MCP process does not listen on a port, so it is fine if multiple agents and OpenClaw each start their own copy. They all point back to the same local Agent Teams desktop control API and shared ~/.claude state.
For a local Mac mini setup, this is straightforward:
1. Run the Agent Teams desktop app.
2. Enable Browser Access / server mode.
3. Configure OpenClaw with the agent-teams MCP server.
4. Let OpenClaw call team_list, team_get, team_create, and team_launch.
5. Use task/message/review MCP tools for deeper coordination.
REST is also available for lifecycle calls like list/create/get/launch/stop, but MCP is the better integration surface for actual AI-to-team work.
```
## 15. Final Recommendation
Start with MCP-first local integration.
Use this minimum viable flow:
```text
1. OpenClaw starts agent-teams-mcp.
2. OpenClaw calls team_get("openclaw-review").
3. If missing, OpenClaw calls team_create(...).
4. OpenClaw calls team_launch(..., waitForReady: true).
5. OpenClaw creates a review task with task_create or sends a message with message_send.
6. OpenClaw reads results via task_get/task_list/message flow.
```
This gives OpenClaw the team coordination behavior without inventing a separate orchestration layer.