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

33 KiB

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:

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:

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

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.

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.

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:

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:

Settings -> Browser Access -> Enable server mode

When enabled, the app starts a local Fastify HTTP server.

Default:

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:

~/.claude/team-control-api.json

Example:

{
  "baseUrl": "http://127.0.0.1:3456",
  "pid": 12345,
  "updatedAt": "2026-04-29T10:00:00.000Z"
}

Check it:

cat ~/.claude/team-control-api.json

Then verify REST:

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:

No tunnel needed.
Use http://127.0.0.1:<port>.

If OpenClaw runs on another machine:

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:

ssh -N -L 3456:127.0.0.1:3456 user@mac-mini-host

Then OpenClaw can use:

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:

{
  "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:

pnpm --filter agent-teams-mcp build

Configure OpenClaw:

{
  "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:

{
  "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:

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:

team_list

Arguments:

{
  "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:

team_get

Arguments:

{
  "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:

team_create

Arguments:

{
  "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:

team_launch

Arguments:

{
  "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:

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:

task_create

Arguments:

{
  "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:

message_send

Arguments:

{
  "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:

team_stop

Arguments:

{
  "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:

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:

http://127.0.0.1:3456

Discover current:

cat ~/.claude/team-control-api.json

Use:

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:

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

curl -s "$BASE_URL/api/teams" | jq .

8.4 Create a Draft Team

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:

{
  "teamName": "openclaw-review"
}

8.5 Get a Draft or Existing Team

curl -s "$BASE_URL/api/teams/openclaw-review" | jq .

Draft shape:

{
  "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

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:

{
  "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

RUN_ID="paste-run-id-here"
curl -s "$BASE_URL/api/teams/provisioning/$RUN_ID" | jq .

Terminal states:

  • ready
  • failed
  • disconnected
  • cancelled

Successful launch:

{
  "state": "ready"
}

8.8 Get Runtime State

curl -s "$BASE_URL/api/teams/openclaw-review/runtime" | jq .

8.9 Stop a Team

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.

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:

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:

lowercase alphanumeric segments separated by single hyphens, max 64 chars

Good:

openclaw-review
repo-audit-1
security-check

Bad:

OpenClaw Review
openclaw_review
review team
review--team
-review
review-

10.2 Member Names

Avoid reserved names:

  • user
  • team-lead

Good:

reviewer
critic
tester
architect

10.3 Providers and Runtime Fields

Provider IDs:

anthropic
codex
gemini
opencode

Provider backend IDs:

auto
adapter
api
cli-sdk
codex-native

Fast mode:

inherit
on
off

Effort values are provider-dependent. Common values include:

low
medium
high

Codex-oriented create flows may also use values such as:

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

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:

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:

team_get

Then reuse the existing team, or pick another teamName.

12.5 team_launch Hangs

With REST, poll:

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:

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:

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.