npx skills add https://github.com/sunqb/ccsdk --skill translateCLI を使用してこのスキルをインストールし、ワークスペースで SKILL.md ワークフローの使用を開始します。
基于 Claude Agent SDK (Python) 的 Agent 服务,完全遵循 cc-agent-sdk 设计理念。
conversationId 进行会话继续model、baseURL、apiKey 覆盖git clone https://github.com/sunqb/ccsdk.git
cd ccsdk
# 使用 uv (推荐)
uv pip install -r requirements.txt
# 或使用 pip
pip install -r requirements.txt
cp .env.example .env
vim .env
必填配置:
ANTHROPIC_API_KEY=your-anthropic-api-key
ANTHROPIC_BASE_URL=https://api.anthropic.com # 可选
ANTHROPIC_MODEL=claude-sonnet-4-5-20250929
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
curl -X POST http://localhost:8000/agent-sdk/stream \
-H "Content-Type: application/json" \
-d '{"prompt": "Hello, Claude!"}'
┌─────────────────────────────────────────────────┐
│ Client │
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ FastAPI Application │
│ │
│ /agent-sdk/stream - 统一调用入口 │
│ /agent-sdk/history - 历史记录 │
│ /agent-sdk/projects - 项目列表 │
│ /agent-sdk/conversations - 会话列表 │
│ │
│ /skills - Skills 管理 (查询/创建) │
│ │
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Claude Agent SDK (Python) │
│ │
│ • settingSources: ["project"] │
│ • 从 .claude/skills/ 加载 Skills │
│ • Claude 根据 description 自动匹配 │
│ │
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Anthropic Claude API │
└─────────────────────────────────────────────────┘
Skills 存放在 .claude/skills/ 目录,SDK 会自动加载:
.claude/skills/
├── Topic_Planning/
│ └── SKILL.md
└── example/
└── SKILL.md
---
name: Topic_Planning
description: 选题策划主入口 - 识别策划场景,引导用户进入对应的专项Skill流程
version: 1.0.0
tags: [topic, planning, router]
---
# 选题策划主入口
## 核心任务
作为选题策划系统的总入口,负责...
无需手动指定 Skill,Claude 会自动判断:
# 用户发送自然语言请求
curl -X POST http://localhost:8000/agent-sdk/stream \
-H "Content-Type: application/json" \
-d '{
"prompt": "《长安的荔枝》选题",
"cwd": "/path/to/project"
}'
# Claude 自动:
# 1. 识别到 "选题" 关键词
# 2. 匹配 Topic_Planning skill 的 description
# 3. 决定是否调用该 Skill
# 4. 如果匹配度高,自动调用
设计哲学:完全信任 Claude 的判断能力,不需要人工指定 Skill 名称。
| 方法 | 端点 | 描述 |
|---|---|---|
| POST | /agent-sdk/stream |
流式查询 (SSE) |
| GET | /agent-sdk/history |
查询会话历史 |
| GET | /agent-sdk/projects |
列出所有项目 |
| GET | /agent-sdk/conversations |
列出所有会话 |
| 方法 | 端点 | 描述 |
|---|---|---|
| GET | /skills |
列出所有 Skills |
| GET | /skills/{name} |
获取 Skill 详情 |
| GET | /skills/{name}/content |
获取 Skill 内容 |
| POST | /skills |
创建新 Skill |
| DELETE | /skills/{name} |
删除 Skill |
注意:没有 /skills/{name}/invoke 端点,因为 Skills 通过 /agent-sdk/stream 自动调用。
请求体:
{
"prompt": "用户提示词",
"conversationId": "会话ID (可选)",
"cwd": "/path/to/project",
"settingSources": ["project"],
"model": "claude-sonnet-4-5-20250929",
"resultMode": "full",
"eventMode": "full",
"options": {
"allowedTools": null,
"maxTurns": 10
}
}
可选参数说明:
eventMode=full:输出完整事件流(默认,尽量与 Claude Code CLI/SDK 保持一致)eventMode=text_only:仅输出 content_block_delta/text_delta(并保留 stream_event/end 与 error);该模式下服务会强制 resultMode=none,避免最后的全量 result响应 (text/event-stream):
data: {"type": "stream_event", "subtype": "start", "conversationId": "xxx"}
data: {"type": "stream_event", "subtype": "init", "data": {...}, "conversationId": "xxx"}
data: {"type": "content_block_delta", "subtype": "text_delta", "data": {"text": "你好!"}, "conversationId": "xxx"}
data: {"type": "result", "subtype": "success", "data": {"result": "..."}, "conversationId": "xxx"}
conversationId(或传一个全新的 ID),服务会创建新会话conversationIdGET /agent-sdk/history?conversationId=...
session_id(位于 stream_event/init.data.session_id,或可通过 GET /agent-sdk/conversations 列出)session_id);若服务重启,需直接使用 Claude Code 的 session_idClaude Agent SDK 底层通过 Claude Code CLI 启动 MCP Server。你需要:
mcpServers(推荐放在项目下,随 cwd 生效)settingSources 覆盖到你放置 settings 的来源(project/user/local)options.allowedTools 限制到排除 MCP(或把对应 mcp__<server>__<tool> 加进去)示例:在 ./.claude/settings.json 配置一个 stdio MCP server(以“搜索类 server”为例,command/args 请以该 server 文档为准)
{
"mcpServers": {
"search": {
"command": "npx",
"args": ["-y", "<mcp-server-package>"],
"env": {
"API_KEY": "从环境变量或明文填写"
}
}
}
}
如果你把配置写在 ./.claude/settings.local.json(不建议提交到 git)
请求里请传:"settingSources": ["project", "local"]
验证是否生效
调用 /agent-sdk/stream,看 stream_event/init 事件里的 mcp_servers 是否出现你的 server 名称;同时 tools 列表里会出现形如 mcp__search__xxx 的工具名。
| 变量名 | 描述 | 默认值 | 必填 |
|---|---|---|---|
ANTHROPIC_API_KEY |
Anthropic API Key | - | ✅ |
ANTHROPIC_AUTH_TOKEN |
同 API_KEY | - | 否 |
ANTHROPIC_BASE_URL |
API Base URL | - | 否 |
ANTHROPIC_MODEL |
使用的模型 | claude-sonnet-4-5-20250929 |
否 |
AGENT_SDK_API_KEY |
API 认证密钥 | - | 否 |
AGENT_SDK_STREAM_RESULT_MODE |
/agent-sdk/stream 的 result(success) 输出模式:`full |
empty | none` |
AGENT_SDK_STREAM_EVENT_MODE |
/agent-sdk/stream 的事件输出模式:`full |
text_only` | full |
AGENT_SDK_ADDITIONAL_SETTINGS_JSON |
通过代码注入 claude --settings <json> 的附加 settings(JSON 字符串) |
- | 否 |
AGENT_SDK_PERMISSIONS_ALLOW |
逗号分隔的 permissions.allow 规则(会合并进 additional settings) |
- | 否 |
AGENT_SDK_MCP_SERVERS_JSON |
通过代码注入 MCP servers(JSON 字符串,形如 {\"search\": {\"type\":\"sse\",\"url\":\"...\"}}) |
- | 否 |
AGENT_SDK_STRICT_MCP_CONFIG |
仅使用注入的 MCP(传 --strict-mcp-config),1/true 启用 |
- | 否 |
HOST |
服务监听地址 | 0.0.0.0 |
否 |
PORT |
服务监听端口 | 8000 |
否 |
WORK_DIR |
工作目录 | 当前目录 | 否 |
SKILLS_DIR |
Skills 目录 | ./.claude/skills |
否 |
ccsdk/
├── app/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置管理
│ ├── auth.py # API Key 认证
│ ├── models/ # 数据模型
│ │ ├── request.py
│ │ └── response.py
│ ├── services/ # 业务逻辑
│ │ ├── agent.py # Agent 服务
│ │ ├── session.py # 会话管理
│ │ ├── skills.py # Skills 管理
│ │ └── history.py # 历史记录
│ └── routers/ # API 路由
│ ├── agent_sdk.py # /agent-sdk/* 端点
│ └── skills.py # /skills/* 端点
│
├── .claude/
│ └── skills/ # Skills 目录
│ ├── Topic_Planning/
│ │ └── SKILL.md
│ └── example/
│ └── SKILL.md
│
├── .env # 环境变量
├── requirements.txt # Python 依赖
├── pyproject.toml # 项目配置
└── README.md # 项目文档
支持 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN 两种环境变量:
# config.py
anthropic_api_key: str = field(
default_factory=lambda: os.getenv("ANTHROPIC_API_KEY") or os.getenv("ANTHROPIC_AUTH_TOKEN", "")
)
SDK 子进程需要完整的环境变量:
# agent.py
env = dict(os.environ) # 继承所有环境变量
env["ANTHROPIC_API_KEY"] = effective_api_key
env["ANTHROPIC_BASE_URL"] = effective_base_url
SSE 响应中正确显示中文:
# agent.py
def to_sse(self) -> str:
return f"data: {json.dumps(self.to_dict(), ensure_ascii=False)}\n\n"
使用 SDK 默认工具集,不限制为 ["Skill"]:
# agent_sdk.py
tools = allowed_tools if allowed_tools is not None else None
默认只加载项目级别配置,避免用户配置冲突:
# agent.py
effective_setting_sources = setting_sources if setting_sources is not None else ["project"]
重要发现:这是因为 WebFetch 的预检(preflight)功能尝试访问 claude.ai 验证域名安全性,但由于网络限制导致验证失败。
解决方案:在 .claude/settings.json 中添加 skipWebFetchPreflight: true 跳过预检:
{
"skipWebFetchPreflight": true
}
Claude Code CLI 的配置加载机制比较复杂,理解优先级关系对于正确配置至关重要:
| 来源 | 说明 | CLI 参数 |
|---|---|---|
--settings |
通过命令行传入的 JSON 配置 | --settings '{"key": value}' |
user |
用户级配置 ~/.claude/settings.json |
--setting-sources user |
project |
项目级配置 {cwd}/.claude/settings.json |
--setting-sources project |
local |
本地配置 {cwd}/.claude/settings.local.json |
--setting-sources local |
1. local (.claude/settings.local.json) ← 最高优先级
2. project (.claude/settings.json)
3. user (~/.claude/settings.json)
4. --settings 参数 ← 最低优先级(会被文件配置覆盖!)
--settings 参数的优先级最低! 当同时指定了 --setting-sources 和 --settings 时:
# 这个命令中,skipWebFetchPreflight 可能不会生效!
claude --settings '{"skipWebFetchPreflight": true}' --setting-sources project ...
如果 .claude/settings.json 中没有 skipWebFetchPreflight 字段,CLI 会使用默认值 false,覆盖掉 --settings 传入的 true。
方案 1(推荐):在项目的 .claude/settings.json 中显式配置
{
"skipWebFetchPreflight": true,
"其他配置": "..."
}
方案 2:不加载任何配置文件,仅使用 --settings
# 将 setting_sources 设为空列表
effective_setting_sources = [] # 不加载 user/project/local 配置
但方案 2 会导致 Skills 无法加载(Skills 需要 project 配置源)。
本项目通过两种方式确保 skipWebFetchPreflight 生效:
代码默认值(config.py):
agent_sdk_additional_settings_json = '{"skipWebFetchPreflight": true}'
项目配置文件(.claude/settings.json):
{"skipWebFetchPreflight": true}
两者缺一不可,因为配置文件会覆盖代码传入的值。
确保 SKILL.md 的 description 字段准确描述功能,Claude 会根据用户 prompt 自动匹配。
settingSources 是否包含 "project".claude/skills/ 目录下是否有 SKILL.mdskills 字段是否包含你的 Skill最新版本已修复,确保使用 ensure_ascii=False 序列化 JSON。
检查 ANTHROPIC_API_KEY 是否正确设置,SDK 子进程是否能访问该环境变量。
检查服务启动日志:
Loaded 2 skills from ./.claude/skills
查看 init 事件的 skills 字段:
{
"skills": ["Topic_Planning", "example"]
}
| 功能 | cc-agent-sdk | 本实现 |
|---|---|---|
| 语言 | TypeScript | Python |
| 框架 | Bun | FastAPI |
| Skills 加载 | ✅ SDK 自动加载 | ✅ SDK 自动加载 |
| Skills 匹配 | ✅ Claude 自动 | ✅ Claude 自动 |
| SSE 流式响应 | ✅ | ✅ |
| 会话管理 | ✅ | ✅ |
| 中文支持 | ✅ | ✅ |
| API 端点 | /agent-sdk/* |
/agent-sdk/* |
| Skills 管理 | 无独立端点 | /skills/* |
pip install -r requirements.txt
pytest
black app/
ruff check app/
docker build -t ccsdk .
docker run -d -p 8000:8000 \
-e ANTHROPIC_API_KEY=xxx \
ccsdk
docker-compose up -d
MIT
欢迎提交 Issue 和 Pull Request!