Add Claude Code AgentRuntime example#377
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a new claude-code-agent example that runs a Claude Code SDK loop inside an AgentCube AgentRuntime, including container build/deploy assets and invocation helpers.
Changes:
- Introduces a FastAPI-based agent server (
agent.py) that invokes Claude Code SDK and exposes health/invoke endpoints. - Adds Kubernetes
AgentRuntimemanifest and a Dockerfile to build/run the example in a sandboxed workspace. - Adds docs and helper client script for invoking the runtime via AgentCube Router / SDK.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| example/claude-code-agent/requirements.txt | Defines Python dependencies for the example server image. |
| example/claude-code-agent/invoke_with_sdk.py | Adds a small client to invoke the deployed AgentRuntime via AgentCube SDK. |
| example/claude-code-agent/claude-code-agent.yaml | Adds a deployable AgentRuntime manifest with environment configuration. |
| example/claude-code-agent/agent.py | Implements the FastAPI server and Claude Code SDK integration. |
| example/claude-code-agent/README.md | Documents build, deploy, and invocation steps for the example. |
| example/claude-code-agent/Dockerfile | Builds the runnable image (Python + Node + Claude Code CLI + server). |
| claude-agent-sdk | ||
| fastapi>=0.115.0 | ||
| uvicorn>=0.34.0 |
| try: | ||
| result = _run_sync(run_claude_agent(prompt=prompt, max_turns=max_turns)) | ||
| except Exception as exc: | ||
| return {"error": str(exc)}, 500 | ||
| return result, 200 |
| try: | ||
| result = await run_claude_agent(prompt=prompt, max_turns=max_turns) | ||
| except Exception as exc: | ||
| return {"error": str(exc)}, 500 | ||
| return result, 200 |
| def _run_sync(value: Any) -> Any: | ||
| if inspect.isawaitable(value): | ||
| return asyncio.run(value) | ||
| return value |
| RUN sed -i "s|http://deb.debian.org/debian-security|${APT_SECURITY_MIRROR}|g; s|http://deb.debian.org/debian|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources \ | ||
| && apt-get update \ | ||
| && apt-get install -y --no-install-recommends ca-certificates curl git xz-utils \ | ||
| && rm -rf /var/lib/apt/lists/* \ | ||
| && case "${TARGETARCH}" in \ | ||
| arm64) node_arch="arm64" ;; \ | ||
| amd64) node_arch="x64" ;; \ | ||
| *) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| esac \ | ||
| && curl -fsSL "${NODE_DIST_BASE}/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" \ | ||
| | tar -xJ --strip-components=1 -C /usr/local \ | ||
| && npm config set registry "${NPM_REGISTRY}" \ | ||
| && npm install -g @anthropic-ai/claude-code |
| image: claude-code-agent:latest | ||
| imagePullPolicy: IfNotPresent |
| client = AgentRuntimeClient( | ||
| agent_name=os.getenv("AGENT_NAME", "claude-code-agent"), | ||
| router_url=os.getenv("ROUTER_URL", "http://localhost:8081"), | ||
| namespace=os.getenv("NAMESPACE", "default"), | ||
| session_id=os.getenv("AGENTCUBE_SESSION_ID") or None, | ||
| timeout=int(os.getenv("TIMEOUT", "300")), | ||
| ) |
| "prompt": os.getenv("PROMPT", "Reply with OK only."), | ||
| "max_turns": int(os.getenv("MAX_TURNS", "3")), | ||
| }, | ||
| timeout=int(os.getenv("TIMEOUT", "300")), |
There was a problem hiding this comment.
Code Review
This pull request introduces a new example for running a Claude Code SDK agent loop inside an AgentCube AgentRuntime sandbox, including a Dockerfile, deployment manifests, a FastAPI-based agent script, and an SDK invocation script. The feedback highlights several key improvements: correcting the invalid DeepSeek model name (deepseek-v4-flash to deepseek-chat) across the code, configuration, and documentation; using official registries instead of regional mirrors in the Dockerfile for better portability; and defensively parsing and clamping the MAX_TURNS environment variable to prevent potential validation or startup failures.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| SERVER_HOST = "0.0.0.0" | ||
| SERVER_PORT = int(os.environ.get("PORT", "8080")) | ||
| WORKSPACE_DIR = os.environ.get("WORKSPACE_DIR", "/workspace") | ||
| MAX_TURNS = int(os.environ.get("MAX_TURNS", "10")) |
There was a problem hiding this comment.
If the MAX_TURNS environment variable is not a valid integer, or if it is configured to be outside the [1, 100] range allowed by the Pydantic schema (InvokeRequest), it can cause startup crashes or validation errors. It is safer to parse and clamp this value defensively.
try:
MAX_TURNS = max(1, min(100, int(os.environ.get("MAX_TURNS", "10"))))
except ValueError:
MAX_TURNS = 10|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #377 +/- ##
===========================================
+ Coverage 47.57% 57.90% +10.33%
===========================================
Files 30 34 +4
Lines 2819 3181 +362
===========================================
+ Hits 1341 1842 +501
+ Misses 1338 1154 -184
- Partials 140 185 +45
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e3b94e1 to
5af81c1
Compare
5af81c1 to
6a16eef
Compare
| WORKDIR /app | ||
|
|
||
| ARG NODE_VERSION=22.11.0 | ||
| ARG TARGETARCH |
| && case "${TARGETARCH}" in \ | ||
| arm64) node_arch="arm64" ;; \ | ||
| amd64) node_arch="x64" ;; \ | ||
| *) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| esac \ |
| def _load_claude_sdk() -> tuple[Callable[..., AsyncIterator[Any]], type]: | ||
| try: | ||
| from claude_agent_sdk import ClaudeAgentOptions as ClaudeCodeOptions, query | ||
| except ImportError as exc: | ||
| try: | ||
| from claude_code_sdk import ClaudeCodeOptions, query | ||
| except ImportError: | ||
| raise RuntimeError( | ||
| "claude-agent-sdk is not installed. Install requirements.txt or rebuild the example image." | ||
| ) from exc | ||
| return query, ClaudeCodeOptions |
| def _run_sync(value: Any) -> Any: | ||
| if inspect.isawaitable(value): | ||
| return asyncio.run(value) | ||
| return value |
| try: | ||
| result = _run_sync(run_claude_agent(prompt=prompt, max_turns=max_turns)) | ||
| except Exception as exc: | ||
| return {"error": str(exc)}, 500 | ||
| return result, 200 |
| try: | ||
| result = await run_claude_agent(prompt=prompt, max_turns=max_turns) | ||
| except Exception as exc: | ||
| return {"error": str(exc)}, 500 | ||
| return result, 200 |
| claude-agent-sdk | ||
| fastapi>=0.115.0 | ||
| uvicorn>=0.34.0 |
Signed-off-by: CYJiang <googs1025@gmail.com>
6a16eef to
c2f83ea
Compare
Adds a small Claude Code SDK example that runs as an AgentRuntime.
Included:
claude-agent-sdkTested locally with Docker build,
kubectl apply --dry-run=client, Router health check, curl invocation, and AgentCube Python SDK invocation.