From Solo Agent to AI Team
In Part 1 you learned what Claude Code is and how it works. In Part 2 you mastered skills, memory, and token optimization. Now it's time to go big.
This guide covers the features that turn Claude Code from a single assistant into a full development pipeline: agent teams that work in parallel, MCP servers that connect Claude to any tool or API, and CI/CD integrations that let Claude Code review PRs, fix bugs, and ship code — all autonomously.
These are the features that make the difference between "I use AI to help me code" and "I have an AI engineering team."
Agent Teams — Multiple Claude Instances Working Together
Subagents (covered in Part 2) are great for isolated tasks. But what if you need multiple agents that communicate with each other, share a task list, and coordinate on complex work? That's what agent teams do.
How Teams Work
One Claude Code session acts as the team lead. It spawns teammates — separate Claude Code instances, each with their own context window. They share a task list and can send messages to each other directly.
The Key Difference: Teams vs Subagents
This is the distinction that matters:
Use subagents when you want isolated, parallel research. Use agent teams when agents need to coordinate, share context, or build on each other's work.
Enabling Agent Teams
Agent teams are experimental. Enable them in your settings:
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}
Or set the environment variable directly:
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
claude
Spawning a Team
Just describe what you want in natural language:
# In Claude Code:
"Create a team with 3 teammates:
1. One to refactor the auth module
2. One to update all the tests
3. One to update the API documentation"
Claude spawns three teammates, assigns tasks, and coordinates the work. Each teammate works in its own context window, on its own files, in parallel.
Display Modes
How you see your team depends on your terminal setup:
Team Communication
Teammates communicate through two mechanisms:
- Direct messages — send to a specific teammate
- Broadcasts — send to all teammates (use sparingly, scales with team size)
The team lead can also read all teammate output and synthesize results. When a teammate finishes its task, it marks it complete and the lead picks up the results.
Best Practices for Teams
- ✔ Start with 3-5 teammates for most workflows
- ✔ Assign different files to each teammate to avoid conflicts
- ✔ Size tasks as self-contained units — each teammate should be able to finish independently
- ✔ Use teams for parallel research — "investigate three different approaches and report back"
- ✘ Don't create too many teammates — coordination overhead increases with team size
- ✘ Don't nest teams — one team per session
- ✘ Don't use teams for trivial tasks — subagents are lighter for simple work
Custom Subagents — Build Your Own Specialists
Beyond the built-in subagents (Explore, Plan, Bash), you can create project-specific agents that know your codebase and follow your rules.
Creating Agents
The easiest way is the interactive command:
/agents
# → Create new agent
# → Choose scope (user or project)
# → Generate with Claude or write manually
Or create a markdown file directly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
name: security-auditor
description: Audits code for security vulnerabilities and OWASP top 10 issues
tools: Read, Glob, Grep, Bash
model: sonnet
permissionMode: default
maxTurns: 10
---
You are a security auditor. When invoked:
1. Scan the specified files for security vulnerabilities
2. Check for OWASP Top 10 issues:
- SQL injection
- XSS
- Broken authentication
- Sensitive data exposure
- CSRF
3. Report findings with severity levels (Critical/High/Medium/Low)
4. Suggest specific fixes for each issue
Save this to .claude/agents/security-auditor.md (project scope) or ~/.claude/agents/security-auditor.md (all projects).
Agent Configuration Fields
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const agentFields = [
{ field: "name", required: true, desc: "Unique identifier" },
{ field: "description", required: true, desc: "When to use this agent" },
{ field: "tools", required: false, desc: "Allowed tools (inherits all if omitted)" },
{ field: "disallowedTools", required: false, desc: "Explicitly blocked tools" },
{ field: "model", required: false, desc: "sonnet | opus | haiku | inherit" },
{ field: "permissionMode", required: false, desc: "default | acceptEdits | dontAsk | bypassPermissions" },
{ field: "maxTurns", required: false, desc: "Maximum agentic turns before stopping" },
{ field: "skills", required: false, desc: "Preload specific skills into agent" },
{ field: "mcpServers", required: false, desc: "MCP servers available to this agent" },
{ field: "memory", required: false, desc: "user | project | local — persistent memory" },
{ field: "background", required: false, desc: "Run in background (true/false)" },
{ field: "isolation", required: false, desc: "worktree — run in isolated git worktree" },
];
console.log("Agent Configuration Fields:");
console.log("=".repeat(55));
agentFields.forEach(f => {
const req = f.required ? "✔ Required" : " Optional";
console.log(` ${req} ${f.field.padEnd(18)} ${f.desc}`);
});
Agent Scopes (Priority Order)
Persistent Agent Memory
Give agents their own persistent memory across sessions:
memory: user # ~/.claude/agent-memory/<name>/
memory: project # .claude/agent-memory/<name>/
memory: local # .claude/agent-memory-local/<name>/
The agent gets a MEMORY.md file (first 200 lines auto-injected) plus access to Read/Write/Edit for additional files. This means your security auditor can remember which vulnerabilities it found before and track fix status across sessions.
Dynamic Agents via CLI
For scripts and automation, define agents inline:
claude --agents '{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer. Focus on quality, security, and best practices.",
"tools": ["Read", "Grep", "Glob"],
"disallowedTools": ["Write", "Edit"],
"model": "sonnet",
"maxTurns": 10
}
}' -p "Review the changes in the last commit"
MCP Servers — Deep Dive
Part 1 introduced MCP. Now let's go deep — adding servers, building integrations, and optimizing for token usage.
Server Types
MCP servers come in three flavors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const serverTypes = [
{
type: "HTTP (recommended)",
transport: "http",
how: "Connects to a remote HTTP endpoint",
example: "claude mcp add --transport http notion https://mcp.notion.com/mcp",
pros: ["Easy setup", "No local process", "Managed by provider"],
cons: ["Requires internet", "Provider rate limits"]
},
{
type: "SSE (deprecated)",
transport: "sse",
how: "Server-Sent Events connection to remote server",
example: "claude mcp add --transport sse legacy https://old-api.example.com/sse",
pros: ["Still works for legacy servers"],
cons: ["Deprecated — migrate to HTTP"]
},
{
type: "Stdio (local process)",
transport: "stdio",
how: "Runs a local process, communicates via stdin/stdout",
example: 'claude mcp add --transport stdio postgres -- npx -y @modelcontextprotocol/server-postgres',
pros: ["No internet needed", "Full control", "Custom logic"],
cons: ["Must install locally", "Uses system resources"]
}
];
console.log("MCP Server Types:");
console.log("=".repeat(55));
serverTypes.forEach(s => {
console.log(`\n🔌 ${s.type}`);
console.log(` Transport: ${s.transport}`);
console.log(` Example: ${s.example}`);
console.log(` Pros: ${s.pros.join(", ")}`);
console.log(` Cons: ${s.cons.join(", ")}`);
});
Adding MCP Servers
# HTTP server (most common)
claude mcp add --transport http notion https://mcp.notion.com/mcp
# HTTP with authentication header
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# Local stdio server with environment variables
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
-- npx -y airtable-mcp-server
# Manage servers
claude mcp list # List all
claude mcp get github # Details for one
claude mcp remove github # Remove
Inside Claude Code, use /mcp to check status and manage connections.
Server Scopes
Where you add a server determines who can use it:
Project-Scoped MCP (Team Sharing)
Create .mcp.json in your project root and commit it to git:
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/"
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}
Notice the ${DATABASE_URL} — MCP configs support environment variable expansion. Each developer sets their own value locally, but the server configuration is shared.
OAuth Authentication
Some MCP servers support OAuth for browser-based login:
# Add server that requires auth
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
# Inside Claude Code, run /mcp and follow the browser login flow
/mcp
Using MCP Resources
MCP servers can expose resources — data you can reference directly in prompts:
# Reference MCP resources with @ in your prompt
@github:issue://123
@docs:file://api/authentication
@postgres:schema://users
Claude fetches the resource and includes it as context. No need to copy-paste issue descriptions or schema definitions.
MCP Prompts as Slash Commands
MCP servers can also expose prompts — predefined workflows available as commands:
# Discover available MCP commands with /
/mcp__github__list_prs
/mcp__github__pr_review 456
/mcp__jira__create_issue "Bug in login flow" high
Token Optimization for MCP
This is critical. Each MCP server adds tool definitions to your context. Five servers with 10 tools each = ~15,000 tokens consumed before you type anything.
Solution: Tool Search
# Auto-enable when tools exceed 10% of context (default)
ENABLE_TOOL_SEARCH=auto
# Custom threshold (5%)
ENABLE_TOOL_SEARCH=auto:5
# Always enabled
ENABLE_TOOL_SEARCH=true
With Tool Search enabled, tool definitions load on-demand instead of all upfront. This gives you an 85-95% reduction in MCP overhead.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const tokenSavings = {
without: {
servers: 5,
toolsPerServer: 10,
tokensPerTool: 300,
total: 5 * 10 * 300,
label: "Without Tool Search"
},
with: {
loadedUpfront: 500,
perQuery: 100,
avgQueriesPerSession: 8,
total: 500 + (100 * 8),
label: "With Tool Search"
}
};
console.log("MCP Token Usage Comparison:");
console.log("=".repeat(50));
console.log(`\n${tokenSavings.without.label}:`);
console.log(` ${tokenSavings.without.servers} servers × ${tokenSavings.without.toolsPerServer} tools × ~${tokenSavings.without.tokensPerTool} tokens`);
console.log(` = ${tokenSavings.without.total.toLocaleString()} tokens consumed upfront`);
console.log(`\n${tokenSavings.with.label}:`);
console.log(` ${tokenSavings.with.loadedUpfront} tokens upfront + ${tokenSavings.with.perQuery} per query`);
console.log(` = ~${tokenSavings.with.total.toLocaleString()} tokens for a typical session`);
console.log(`\nSavings: ${((1 - tokenSavings.with.total / tokenSavings.without.total) * 100).toFixed(0)}% reduction`);
CI/CD Integration — Claude Code in Your Pipeline
This is where things get really powerful. Claude Code can run in CI/CD pipelines to review PRs, fix issues, and even implement features — all autonomously.
GitHub Actions
Anthropic provides an official GitHub Action: anthropics/claude-code-action@v1.
Quick Setup
The fastest way to set it up:
# Inside Claude Code:
/install-github-app
# Follows a guided setup for the GitHub app + secrets
Manual Setup
- Install the Claude GitHub app: github.com/apps/claude
- Add
ANTHROPIC_API_KEY to your repository secrets
- Create the workflow file:
# .github/workflows/claude.yml
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
runs-on: ubuntu-latest
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
That's it. Now anyone can mention @claude in a PR comment and it will respond — reading the code, making suggestions, or even pushing fixes.
Advanced Configuration
# Auto-review every PR
name: Claude PR Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "/review"
claude_args: "--max-turns 5 --model claude-sonnet-4-6"
Action Parameters
const actionParams = [
{ param: "anthropic_api_key", required: true, desc: "Your Claude API key" },
{ param: "prompt", required: false, desc: "Instructions or skill (e.g., '/review')" },
{ param: "claude_args", required: false, desc: "CLI arguments (--max-turns, --model, etc.)" },
{ param: "github_token", required: false, desc: "GitHub API token for PR operations" },
{ param: "trigger_phrase", required: false, desc: "Custom trigger (default: '@claude')" },
{ param: "use_bedrock", required: false, desc: "Use AWS Bedrock instead of Claude API" },
{ param: "use_vertex", required: false, desc: "Use Google Vertex AI instead" },
];
console.log("GitHub Action Parameters:");
console.log("=".repeat(55));
actionParams.forEach(p => {
const req = p.required ? "✔ Required" : " Optional";
console.log(` ${req} ${p.param.padEnd(20)} ${p.desc}`);
});
Headless Mode — Claude Code Without a Terminal
For scripts and automation, use print mode (-p flag). Claude processes the input and exits — no interactive session:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Simple query
claude -p "Summarize this project's architecture"
# Process piped input
cat error.log | claude -p "What caused this crash?"
# Get structured JSON output
claude -p "List all API endpoints" \
--output-format json \
--json-schema '{"type":"object","properties":{"endpoints":{"type":"array","items":{"type":"string"}}}}'
# Auto-approve tools for automation
claude -p "Run tests and fix failures" \
--allowedTools "Bash,Read,Edit" \
--max-turns 10
# Budget limit
claude -p "Refactor the auth module" \
--max-budget-usd 5.00 \
--permission-mode acceptEdits
Real-World Pipeline Examples
Auto-Fix Linting Errors
name: Auto-Fix Lint
on:
push:
branches: [feature/*]
jobs:
fix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "Run lint, fix all errors, and commit the fixes"
claude_args: "--max-turns 5 --allowedTools Bash,Read,Edit"
Auto-Generate PR Descriptions
#!/bin/bash
# .github/scripts/generate-pr-description.sh
DIFF=$(gh pr diff "$1")
DESCRIPTION=$(echo "$DIFF" | claude -p \
"Generate a clear, concise PR description for these changes.
Include: summary, key changes, testing notes." \
--output-format json | jq -r '.result')
gh pr edit "$1" --body "$DESCRIPTION"
Security Scan on Every PR
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
name: Security Scan
on:
pull_request:
types: [opened, synchronize]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
Review this PR for security vulnerabilities. Check for:
- SQL injection
- XSS vulnerabilities
- Hardcoded credentials
- Insecure dependencies
- Missing input validation
Comment on the PR with findings.
claude_args: "--max-turns 8"
GitLab CI/CD
Claude Code also works with GitLab:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
stages:
- ai
claude-review:
stage: ai
image: node:24-alpine3.21
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
before_script:
- apk update && apk add --no-cache git curl bash
- curl -fsSL https://claude.ai/install.sh | bash
script:
- >
claude
-p "Review this MR and suggest improvements"
--permission-mode acceptEdits
--allowedTools "Bash Read Edit Write"
Building Custom Pipelines
Now let's combine everything — agent teams, MCP servers, CI/CD, and headless mode — into custom automation pipelines.
Pipeline Pattern 1: The Review Bot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const reviewPipeline = {
trigger: "PR opened or updated",
steps: [
{
step: 1,
agent: "Claude Code Action",
action: "Read PR diff and changed files",
tools: "Read, Grep, Glob"
},
{
step: 2,
agent: "Security auditor subagent",
action: "Scan for OWASP Top 10 vulnerabilities",
tools: "Read, Grep"
},
{
step: 3,
agent: "Performance reviewer subagent",
action: "Check for N+1 queries, unnecessary re-renders",
tools: "Read, Grep"
},
{
step: 4,
agent: "Main agent",
action: "Synthesize findings and comment on PR",
tools: "Bash (gh pr comment)"
}
]
};
console.log("Review Bot Pipeline:");
console.log("=".repeat(50));
reviewPipeline.steps.forEach(s => {
console.log(`\n Step ${s.step}: ${s.agent}`);
console.log(` Action: ${s.action}`);
console.log(` Tools: ${s.tools}`);
});
Pipeline Pattern 2: The Issue Implementer
# When someone labels an issue "claude-implement":
claude -p "Read GitHub issue #$ISSUE_NUMBER.
Implement the requested feature.
Create a branch, make changes, run tests, open a PR." \
--allowedTools "Bash,Read,Edit,Write" \
--max-turns 20 \
--max-budget-usd 10.00
Pipeline Pattern 3: The Migration Assistant
# Multi-agent migration pipeline
claude --agents '{
"schema-migrator": {
"description": "Handles database schema changes",
"prompt": "You handle database migrations. Create migration files, update schemas.",
"tools": ["Read", "Write", "Bash"],
"maxTurns": 10
},
"type-updater": {
"description": "Updates TypeScript types after schema changes",
"prompt": "You update TypeScript types to match database schema changes.",
"tools": ["Read", "Edit", "Grep"],
"maxTurns": 8
}
}' -p "Migrate the users table: add email_verified boolean, remove legacy_auth column"
Pipeline Pattern 4: Structured Output for Tooling
Claude Code can output structured JSON for consumption by other tools:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Get structured data from codebase analysis
claude -p "Analyze all API endpoints" \
--output-format json \
--json-schema '{
"type": "object",
"properties": {
"endpoints": {
"type": "array",
"items": {
"type": "object",
"properties": {
"method": {"type": "string"},
"path": {"type": "string"},
"auth": {"type": "boolean"},
"description": {"type": "string"}
}
}
}
}
}'
This outputs validated JSON you can pipe into documentation generators, API testing tools, or monitoring systems.
The Complete CLI for Automation
Here are the flags that matter most for pipelines and automation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const automationFlags = {
"Execution": {
"-p, --print": "Non-interactive mode — process and exit",
"--max-turns <n>": "Limit agentic turns (prevents runaway agents)",
"--max-budget-usd <n>": "Spending cap before stopping",
"--permission-mode <mode>": "acceptEdits | bypassPermissions for automation",
"--allowedTools <list>": "Auto-approve specific tools",
},
"Input/Output": {
"--output-format json": "Structured JSON output",
"--output-format stream-json": "Streaming events for real-time processing",
"--json-schema <schema>": "Enforce output structure with JSON Schema",
"--input-format stream-json": "Accept streaming input",
},
"Context": {
"--system-prompt <text>": "Replace entire system prompt",
"--append-system-prompt <text>": "Add to default prompt",
"-c, --continue": "Resume last conversation",
"-r, --resume <id>": "Resume specific session",
},
"Agents": {
"--agent <name>": "Use specific agent for session",
"--agents <json>": "Define agents inline (JSON)",
"--teammate-mode <mode>": "auto | in-process | tmux",
}
};
Object.entries(automationFlags).forEach(([category, flags]) => {
console.log(`\n${category}:`);
console.log("─".repeat(55));
Object.entries(flags).forEach(([flag, desc]) => {
console.log(` ${flag.padEnd(32)} ${desc}`);
});
});
Putting It All Together
Here's how everything connects in a real-world workflow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
const fullWorkflow = [
{
phase: "Development (Local)",
tools: "Claude Code CLI + MCP servers + Agent Teams",
flow: [
"Start session → CLAUDE.md + Memory auto-loaded",
"Complex feature → Spawn agent team (3 teammates)",
"Database work → MCP postgres server for schema queries",
"GitHub context → MCP github server for issue details",
"Code review → Custom security-auditor subagent",
]
},
{
phase: "Pre-Commit (Local)",
tools: "Hooks + Skills",
flow: [
"PostToolUse hook → Auto-format with Prettier",
"PreToolUse hook → Block edits to .env files",
"/deploy-check skill → Build, test, lint, type-check",
]
},
{
phase: "CI/CD (Remote)",
tools: "GitHub Actions + Headless Mode",
flow: [
"PR opened → Claude Code Action auto-reviews",
"@claude mention → Responds with fixes or suggestions",
"Security scan → Custom agent checks for vulnerabilities",
"Auto-fix → Claude pushes lint fixes directly",
]
},
{
phase: "Monitoring (Ongoing)",
tools: "Headless mode + Structured output",
flow: [
"Nightly scan → claude -p analyzes codebase health",
"JSON output → Feeds dashboards and alerts",
"Issue triage → Auto-label and prioritize new issues",
]
}
];
console.log("The Complete Claude Code Pipeline:");
console.log("=".repeat(55));
fullWorkflow.forEach(phase => {
console.log(`\n🔧 ${phase.phase}`);
console.log(` Tools: ${phase.tools}`);
phase.flow.forEach(step => {
console.log(` → ${step}`);
});
});
Limitations to Keep in Mind
Before going all-in on multi-agent and CI/CD workflows:
- ✘ Agent teams are experimental — behavior may change, enable manually
- ✘ One team per session — no nested teams
- ✘ Teammates can conflict on files — assign different files to different agents
- ✘ CI costs add up — use
--max-budget-usd and --max-turns to cap spending
- ✘ Headless mode needs explicit permissions — use
--allowedTools to whitelist
- ✘ Tool Search requires Sonnet 4+ — Haiku doesn't support on-demand tool loading
- ✘ MCP servers add context overhead — always enable Tool Search for 3+ servers
Conclusion
Claude Code started as a terminal assistant. With agent teams, MCP integrations, and CI/CD pipelines, it becomes a full development platform.
The progression:
- Part 1 — Learn what Claude Code is and how it works
- Part 2 — Master skills, memory, and token optimization
- Part 3 (this post) — Scale with teams, connect with MCP, automate with CI/CD
- Part 4 — Remote Control — continue sessions from your phone
The developers getting the most value aren't using Claude Code for autocomplete. They're building agent teams that refactor codebases in parallel, MCP integrations that give Claude access to their entire toolchain, and CI/CD pipelines that review, fix, and ship code autonomously.
Pro Tip: Start small. Add one MCP server (GitHub is the most useful). Set up the GitHub Action for PR reviews. Create one custom subagent for your most common workflow. Once you see the value, scale up to teams and full pipelines. The tooling supports it — you just need to build the habit.
Happy coding — and let your agents do the heavy lifting!