Skip to main content

Claude Code SDK and Agent Communication

24/28
Chapter 6 Multi-Agent Architectures

Claude Code SDK and Agent Communication

18 min read Lesson 24 / 28

Claude Code SDK and Agent Communication

The Claude Code SDK allows you to programmatically control Claude Code — Anthropic's official CLI — as an autonomous coding agent within your own applications and pipelines.

Claude Code SDK Overview

Claude Code can be used as:

  1. An interactive CLI for developers
  2. A non-interactive automation target via the SDK
  3. An agent within a larger multi-agent system
import subprocess
import json

def run_claude_code(prompt: str, working_dir: str, allowed_tools: list[str] = None) -> dict:
    """Run Claude Code programmatically via the CLI SDK."""
    cmd = ["claude", "--output-format", "json", "--no-interactive"]

    if allowed_tools:
        cmd.extend(["--allowedTools", ",".join(allowed_tools)])

    cmd.extend(["--message", prompt])

    result = subprocess.run(
        cmd,
        cwd=working_dir,
        capture_output=True,
        text=True,
    )

    if result.returncode != 0:
        raise RuntimeError(f"Claude Code failed: {result.stderr}")

    return json.loads(result.stdout)


# Use Claude Code as a coding subagent
coding_result = run_claude_code(
    prompt="Add input validation to the user registration endpoint. Follow existing patterns.",
    working_dir="/path/to/project",
    allowed_tools=["Read", "Edit", "Bash"],
)

Agent-to-Agent Communication Patterns

When agents need to hand off context to each other, structured message passing prevents information loss:

from dataclasses import dataclass, asdict
from typing import Any
import json
import anthropic

client = anthropic.Anthropic()

@dataclass
class AgentMessage:
    sender: str
    recipient: str
    task: str
    context: dict[str, Any]
    result: str | None = None
    status: str = "pending"  # pending | complete | failed

def send_to_agent(message: AgentMessage, agent_system_prompt: str) -> AgentMessage:
    """Send a structured message to an agent and return its response."""
    prompt = f"""You have received the following task from {message.sender}:

Task: {message.task}

Context:
{json.dumps(message.context, indent=2)}

Complete the task and provide your result."""

    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=2048,
        system=agent_system_prompt,
        messages=[{"role": "user", "content": prompt}],
    )

    message.result = response.content[0].text
    message.status = "complete"
    return message


# Example: orchestrator delegates to a writer agent
task = AgentMessage(
    sender="orchestrator",
    recipient="writer_agent",
    task="Write a 3-paragraph executive summary",
    context={
        "research_findings": "AI adoption is accelerating...",
        "target_audience": "C-suite executives",
        "tone": "professional and concise",
    },
)

completed = send_to_agent(
    task,
    "You are an expert technical writer specializing in executive communications."
)

print(completed.result)

Designing Agent Interfaces

Treat agent interfaces like APIs — define clear input/output contracts:

# Good: explicit, typed interface
def analyze_sentiment(texts: list[str]) -> list[dict]:
    """
    Input: list of strings
    Output: list of {"text": str, "sentiment": str, "confidence": float}
    """
    pass

# Bad: opaque interface that returns raw LLM text
def analyze_stuff(data: str) -> str:
    pass

Structured agent communication makes multi-agent systems debuggable, testable, and composable.