架构约束:所有工具对外统一为本地 Python/FastAPI 调用层(uv 管理)。
SourceType/BackendRuntime表示工具内部的后端执行环境,不是调用方式。
| 枚举 | 值 | 说明 |
|---|---|---|
| ToolStatus | active, inactive, staging, building |
工具生命周期状态 |
| MessageType | tool_request, tool_ready, tool_error, health_alert |
内部消息类型 |
| ContainerStatus | running, destroyed |
容器状态 |
| SourceType | local, docker, remote |
工具来源类型(后端执行环境) |
| ProcessState | stopped, starting, running, error |
进程运行状态 |
{
"tool_id": "image_compress_api",
"name": "图片压缩 API",
"category": "cv",
"description": "基于 PIL 的图片压缩服务",
"input_schema": {
"type": "object",
"properties": {
"image_path": {"type": "string"},
"quality": {"type": "integer", "minimum": 1, "maximum": 100}
},
"required": ["image_path"]
},
"output_schema": {
"type": "object",
"properties": {
"compressed_size": {"type": "integer"},
"compression_ratio": {"type": "number"}
}
},
"stream_support": false,
"status": "active"
}
{
"type": "local",
"host_dir": "tools/local/image_compress_api",
"endpoint_path": "/",
"http_method": "POST",
"internal_port": 0
}
Docker 类型:
{
"type": "docker",
"container_id": "25e884ca6cec...",
"image": "ubuntu:22.04",
"internal_port": 8080,
"endpoint_path": "/api/compress",
"http_method": "POST"
}
Hub 类型(外部 API):
{
"type": "remote",
"remote_url": "https://api.example.com",
"remote_path": "/v1/compress",
"remote_api_key": "sk-***",
"endpoint_path": "/v1/compress",
"http_method": "POST"
}
{
"tool_id": "image_compress_api",
"sources": [
{"type": "local", "host_dir": "tools/local/image_compress_api"}
],
"active_source": 0,
"state": "running",
"pid": 12345,
"port": 52341,
"started_at": "2026-03-26T10:30:00Z",
"last_error": null
}
{
"container_id": "25e884ca6cecfa87e19ea737315a8773d...",
"tool_id": "test_git_tool",
"image": "ubuntu:22.04",
"port_mapping": {"8080": 9001, "3306": 9002},
"volumes": {"C:/staging/project": "/app"},
"mem_limit": "1g",
"nano_cpus": 1000000000,
"use_gpu": false,
"gpu_count": -1,
"status": "running",
"created_at": "2026-03-20T07:31:50.421101Z",
"last_accessed": "2026-03-20T07:33:16.214642+00:00",
"destroyed_at": null
}
路径:data/registry.json
{
"tools": [
{
"tool_id": "image_compress_api",
"name": "图片压缩 API",
"category": "cv",
"description": "基于 PIL 的图片压缩",
"input_schema": {},
"output_schema": {},
"stream_support": false,
"status": "active"
}
],
"version": "2.0"
}
ToolRegistry 类方法:
| 方法 | 参数 | 返回 |
|---|---|---|
get(tool_id) |
tool_id | ToolMeta | None |
list_all() |
- | list[ToolMeta] |
list_active() |
- | list[ToolMeta] |
find_by_category(category) |
category | list[ToolMeta] |
search(keyword) |
keyword | list[ToolMeta] |
register(tool) |
ToolMeta | None |
unregister(tool_id) |
tool_id | bool |
destroy(tool_id) |
tool_id | dict(清理结果) |
路径:data/sources.json
{
"sources": {
"image_compress_api": [
{
"type": "local",
"host_dir": "tools/local/image_compress_api",
"endpoint_path": "/",
"http_method": "POST",
"internal_port": 0
}
],
"gpu_tool": [
{
"type": "docker",
"container_id": "abc123...",
"internal_port": 8080,
"endpoint_path": "/api/run",
"http_method": "POST"
}
]
}
}
| 方法 | 参数 | 返回 |
|---|---|---|
load() |
- | dict[str, list[dict]] |
save(sources) |
sources | None |
add_source(tool_id, source) |
tool_id, ToolSource | None |
get_sources(tool_id) |
tool_id | list[ToolSource] |
remove_tool(tool_id) |
tool_id | None |
路径:data/containers.json
{
"containers": [
{
"container_id": "25e884ca6cec...",
"tool_id": "gpu_tool",
"image": "ubuntu:22.04",
"port_mapping": {"8080": 9001},
"volumes": {"C:/staging/project": "/app"},
"mem_limit": "1g",
"nano_cpus": 1000000000,
"use_gpu": false,
"status": "running",
"created_at": "2026-03-20T07:31:50Z"
}
]
}
Router 生成任务书,通过 asyncio.create_task 提交给 CodingAgent。
{
"type": "github_deploy",
"repo_url": "https://github.com/user/project",
"tool_name": "project_api",
"runtime": "docker",
"description": "将该项目部署为 HTTP API 工具"
}
{
"type": "build_tool",
"tool_name": "text_summarizer_api",
"runtime": "uv",
"description": "编写一个文本摘要工具,接受文本输入,返回摘要"
}
{
"type": "repair_tool",
"tool_id": "image_compress_api",
"error": "HTTP 503: Service Unavailable",
"description": "工具健康检查失败,需要诊断并修复"
}
Router 与 CodingAgent 通过 MessageBus(asyncio.Queue)通信。
当前状态:MessageBus 已实现但未集成,Router 通过直接函数调用启动 CodingAgent。
{
"type": "tool_request | tool_ready | tool_error | health_alert",
"payload": {}
}
{
"type": "tool_request",
"payload": {
"task_spec": "{ /* 任务书 JSON */ }",
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"description": "需要一个图片压缩工具",
"reference_files": ["tools/local/example/main.py"]
}
}
{
"type": "tool_ready",
"payload": {
"tool_id": "image_compress_api",
"result": "部署成功,工具已注册",
"task_id": "550e8400-..."
}
}
{
"type": "tool_error",
"payload": {
"tool_id": "failed_tool",
"error": "依赖安装失败:torch 需要 CUDA 但未检测到 GPU",
"task_id": "550e8400-..."
}
}
{
"type": "health_alert",
"payload": {
"tool_id": "image_compress_api",
"error": "HTTP 503",
"last_healthy": "2026-03-20T10:00:00Z"
}
}
基础地址:http://localhost:8001
// Response
{"status": "ok"}
搜索可用工具列表,返回工具信息及运行状态。
// Request
{
"keyword": "图片",
"category": "cv"
}
// Response
{
"tools": [
{
"tool_id": "image_compress_api",
"name": "图片压缩 API",
"category": "cv",
"description": "基于 PIL 的图片压缩",
"params": [
{
"name": "image_path",
"type": "string",
"description": "图片路径",
"required": true
}
],
"required_params": ["image_path"],
"input_schema": {},
"output_schema": {},
"backend_runtime": "local",
"host_dir": "tools/local/image_compress_api",
"endpoint_path": "/",
"http_method": "POST",
"state": "running",
"port": 52341,
"pid": 12345
}
],
"total": 1
}
选择并调用工具(未启动则自动启动)。
// Request
{
"tool_id": "image_compress_api",
"params": {"image_path": "/path/to/img.jpg", "quality": 85},
"stream": false
}
// Response
{
"status": "success",
"result": {"compressed_size": 256000, "compression_ratio": 0.25},
"error": null
}
提交新工具创建需求(异步)。
// Request
{
"description": "需要一个图片压缩工具",
"task_spec": "详细任务描述..."
}
// Response
{
"task_id": "create_a1b2c3d4",
"status": "pending",
"message": "Task submitted"
}
查询异步任务状态。
// Response
{
"task_id": "create_a1b2c3d4",
"status": "completed",
"result": "工具已成功注册",
"task_spec": "..."
}
列出所有工具运行状态。
// Response
{
"tools": [
{
"tool_id": "image_compress_api",
"sources": [...],
"active_source": 0,
"state": "running",
"pid": 12345,
"port": 52341
}
]
}
手动启动工具。
// Response
{
"tool_id": "image_compress_api",
"state": "running",
"port": 52341
}
手动停止工具。
// Response
{
"tool_id": "image_compress_api",
"state": "stopped"
}
与 Router Agent 对话交互(自然语言)。
设计理念:外部 Agent 通过自然语言与 Router 交互,Router 理解意图后返回结构化方案,更加人性化和灵活。
支持场景:
// Request
{
"message": "用户的自然语言请求",
"context": {} // 可选的上下文信息
}
// Response
{
"reply": "Router 的回复",
"tools": [], // 相关工具列表(可选)
"solution": {}, // 解决方案(可选)
"task_id": "", // 任务 ID(创建工具时)
"next_steps": [] // 后续操作建议
}
示例 1:工具发现
// Request
{
"message": "我需要处理图片的工具",
"context": {"task": "批量压缩图片"}
}
// Response
{
"reply": "找到 2 个图片处理工具,推荐使用 image_compress_api",
"tools": [
{
"tool_id": "image_compress_api",
"name": "图片压缩 API",
"reason": "专门用于图片压缩,支持质量调节",
"usage_example": {
"params": {"image_path": "/path/to/image.jpg", "quality": 85}
}
}
],
"next_steps": ["调用 /select_tool 使用该工具"]
}
示例 2:ComfyUI 工具使用指导
// Request
{
"message": "如何使用 ComfyUI 的 LoadImage 和 SaveImage 节点?"
}
// Response
{
"reply": "ComfyUI 节点已通过 runcomfy 工具接入,需要三步操作",
"solution": {
"type": "composite_workflow",
"base_tools": ["runcomfy_launch_env", "runcomfy_run_only", "runcomfy_stop_env"],
"steps": [
{
"step": 1,
"action": "启动环境",
"tool": "runcomfy_launch_env",
"params": {},
"returns": "container_id"
},
{
"step": 2,
"action": "执行 workflow",
"tool": "runcomfy_run_only",
"params": {
"container_id": "<from_step_1>",
"workflow": {
"nodes": [
{"id": 1, "type": "LoadImage", "inputs": {"image": "input.png"}},
{"id": 2, "type": "SaveImage", "inputs": {"images": ["1", 0]}}
]
}
}
},
{
"step": 3,
"action": "清理环境",
"tool": "runcomfy_stop_env",
"params": {"container_id": "<from_step_1>"}
}
]
}
}
示例 3:工具创建
// Request
{
"message": "帮我创建一个文本摘要工具",
"context": {"requirements": "支持中英文,最大长度 500 字"}
}
// Response
{
"reply": "已提交工具创建任务,预计 2-3 分钟完成",
"task_id": "create_a1b2c3d4",
"status": "pending",
"tracking": "使用 GET /tasks/create_a1b2c3d4 查询进度",
"estimated_time": "2-3 分钟"
}
CodingAgent 通过 claude_agent_sdk 暴露以下 10 个工具:
| 工具 | 必填参数 | 可选参数 | 返回 |
|---|---|---|---|
create_docker_env |
image |
mem_limit, nano_cpus, ports, volumes, use_gpu |
container_id, port_mapping |
run_in_docker |
container_id, command |
is_background, timeout |
exit_code, stdout, stderr 或 log_file |
rebuild_docker_ports |
container_id, ports |
mem_limit, nano_cpus |
new_container_id, port_mapping |
destroy_docker_env |
container_id |
— | status, message |
| 工具 | 必填参数 | 可选参数 | 返回 |
|---|---|---|---|
create_uv_project |
name |
python_version |
project_dir |
run_in_uv |
project_dir, command |
is_background, timeout |
exit_code, stdout, stderr |
uv_add_dependency |
project_dir, package |
dev |
status, message |
| 工具 | 必填参数 | 返回 |
|---|---|---|
write_file |
path, content |
status, path, size |
read_file |
path |
status, path, content |
| 工具 | 必填参数 | 可选参数 | 返回 |
|---|---|---|---|
register_tool |
tool_id, name, description, runtime_type, internal_port |
category, input_schema, output_schema, container_id, host_dir, endpoint_path, http_method, group_ids |
status, tool_id, backend_runtime, message |
TOOL_AGENT_)| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
fastapi_port |
int | 8001 |
对外 HTTP 端口 |
mcp_port |
int | 8001 |
MCP Server 端口 |
docker_port_start |
int | 9001 |
Docker 端口起始 |
docker_base_image |
str | "agent-sandbox:latest" |
默认基础镜像 |
docker_mem_limit |
str | "1g" |
默认容器内存 |
docker_nano_cpus |
int | 1000000000 |
默认 CPU(1 核) |
docker_ttl_seconds |
int | 1800 |
容器自动清理 TTL |
cold_tool_idle_timeout_s |
int | 300 |
冷工具空闲超时 |
hot_tool_max_containers |
int | 5 |
最大热工具容器数 |
eviction_policy |
str | "lru" |
置换策略 |
monthly_limit_usd |
float | 100.0 |
月预算上限 |
single_tx_limit_usd |
float | 20.0 |
单笔上限 |
require_approval_above_usd |
float | 10.0 |
需审批阈值 |
health_check_interval_s |
int | 60 |
健康检查间隔 |
Router 负责与外部 Agent 对话,将自身工具库与外部工具表进行匹配和对接。
当外部 Agent 请求工具时,Router 执行以下匹配逻辑:
外部 Agent 请求工具 X
│
▼
Router 查询 registry.json
│
├─ 直接匹配:tool_id 或 name 完全匹配
│ → 返回工具信息,调用 /select_tool
│
├─ 模糊匹配:keyword 匹配 description
│ → 返回候选列表,由外部 Agent 选择
│
├─ 组合工具匹配:检测是否为复合工具需求
│ → 例如:ComfyUI 节点工具
│ → 检查是否有基础工具(如 runcomfy)
│ → 返回基础工具 + 使用说明
│
└─ 无匹配:返回 404
→ 外部 Agent 可选择提交 /create_tool 请求
场景:外部 Agent 请求使用 ComfyUI 内部节点(如 LoadImage, SaveImage)
Router 响应策略:
检测 ComfyUI 相关关键词:
comfyui, workflow, node 等关键词查询基础工具:
runcomfy 相关工具runcomfy_launch_env, runcomfy_run_only, runcomfy_stop_env返回组合工具信息:
{
"status": "composite_tool",
"message": "ComfyUI 节点工具已通过 runcomfy 基础工具接入",
"base_tools": [
{
"tool_id": "runcomfy_launch_env",
"name": "启动 ComfyUI 环境",
"description": "启动 ComfyUI Docker 环境,返回容器 ID 和端口",
"usage": "先调用此工具启动环境,获取 container_id"
},
{
"tool_id": "runcomfy_run_only",
"name": "执行 ComfyUI Workflow",
"description": "在已启动的环境中执行 workflow JSON",
"usage": "传入 workflow JSON 和 container_id,执行节点流程"
},
{
"tool_id": "runcomfy_stop_env",
"name": "停止 ComfyUI 环境",
"description": "停止并清理 ComfyUI 容器",
"usage": "任务完成后调用,释放资源"
}
],
"workflow_example": {
"description": "使用 LoadImage 和 SaveImage 节点的示例",
"steps": [
"1. 调用 runcomfy_launch_env 启动环境",
"2. 构造 workflow JSON(包含 LoadImage, SaveImage 节点)",
"3. 调用 runcomfy_run_only 执行 workflow",
"4. 获取输出结果",
"5. 调用 runcomfy_stop_env 清理环境"
],
"workflow_json": {
"nodes": [
{"id": 1, "type": "LoadImage", "inputs": {"image": "input.png"}},
{"id": 2, "type": "SaveImage", "inputs": {"images": ["1", 0]}}
]
}
}
}
Router 提供以下内部方法支持工具匹配:
| 方法 | 参数 | 返回 | 说明 |
|---|---|---|---|
match_tool(query) |
query: str | ToolMeta | None | 精确匹配 tool_id 或 name |
search_tools(keyword, category) |
keyword, category | list[ToolMeta] | 模糊搜索 |
detect_composite_tool(query) |
query: str | dict | None | 检测是否为组合工具需求 |
get_base_tools(composite_type) |
composite_type: str | list[ToolMeta] | 获取基础工具列表 |
未来规划:Router 可对接外部工具表(如其他 Agent 系统的工具库)
// 外部工具表注册
POST /external_tools/register
{
"source": "agent_system_x",
"tools_url": "https://agent-x.com/api/tools",
"api_key": "sk-***"
}
// Router 查询时同时搜索本地 + 外部工具表
// 返回统一格式的工具列表
路径:{project_dir}/last_run.log
Command: python main.py
Exit Code: 0
--- STDOUT ---
Server started on port 8080
--- STDERR ---
WARNING: Using development server
2026-03-26 15:09:32 [tool_agent.tool.agent] INFO: [CodingAgent] Starting task: 部署 flask 项目...
2026-03-26 15:09:35 [tool_agent.tool.agent] INFO: [TOOL_USE] create_docker_env | {"image":"python:3.12-slim","ports":[8080]}
2026-03-26 15:09:40 [tool_agent.tool.agent] INFO: [TEXT] 正在创建 Docker 环境...
2026-03-26 15:10:15 [tool_agent.tool.agent] INFO: [TOOL_USE] register_tool | {"tool_id":"flask_api",...}
2026-03-26 15:10:16 [tool_agent.tool.agent] INFO: [DONE] duration=44000ms
2026-03-26 15:10:16 [tool_agent.tool.agent] INFO: [COST] $0.12