# CodingAgent 工具创建任务书编写指南 本文档说明如何为 CodingAgent 准备任务书,让它自动创建和封装工具。 ## 目录 - [工作流程](#工作流程) - [任务书必需参数](#任务书必需参数) - [任务书模板](#任务书模板) - [JSON Schema 编写规范](#json-schema-编写规范) - [提交任务](#提交任务) - [常见问题](#常见问题) --- ## 工作流程 CodingAgent 自动化工具创建流程分为5个阶段: ### 阶段1: 环境准备 1. 生成唯一任务ID: `task_{8位随机字符}` 2. 创建临时工作目录: `data/staging/{task_id}/` 3. 初始化开发环境 ### 阶段2: 工具开发 1. **选择运行环境**: - 纯Python + 简单依赖 → 使用 `uv` (快速启动) - 需要端口/服务/GPU/系统库 → 使用 `Docker` + 卷挂载 2. **实现核心逻辑**: - 编写业务逻辑代码 - 创建 FastAPI HTTP 接口封装 - 添加依赖到 `pyproject.toml` 3. **测试核心功能**: - 在 `tests/` 目录编写单元测试 - 测试输出保存到 `tests/output/` - **注意**: 只测试核心逻辑,不测试HTTP服务启动 ### 阶段3: 服务启动与验证 1. 后台启动 HTTP 服务 2. 验证健康检查端点: `GET /health` 3. 测试业务逻辑端点 ### 阶段4: 工具注册 调用 `register_tool` 将工具注册到系统: - 保存元数据到 `data/registry.json` - 保存路由信息到 Router 的 SourceStore ### 阶段5: 完成报告 返回工具创建摘要,包含: - 工具名称和ID - 功能描述 - 访问方法 - 注册状态 --- ## 任务书必需参数 ### 1. 工具标识 (必需) ```markdown ## 工具标识 - **tool_id**: `your_tool_name` 格式: 小写字母+下划线,匹配正则 `^[a-z][a-z0-9_]*$` - **工具名称**: 工具的显示名称 (中文或英文) - **工具描述**: 简洁描述工具功能 (1-2句话) - **分类** (可选): `cv` (计算机视觉), `ai` (AI生成), `nlp` (自然语言处理), `audio` (音频处理) 等 ``` ### 2. 功能需求 (必需) ```markdown ## 功能需求 ### 核心功能1 - 功能描述 - 输入要求 - 输出格式 ### 核心功能2 - ... ``` ### 3. 输入Schema (必需) 使用 JSON Schema 格式定义输入参数: ```markdown ## 输入Schema \`\`\`json { "type": "object", "required": ["param1", "param2"], "properties": { "param1": { "type": "string", "description": "参数1的描述" }, "param2": { "type": "integer", "default": 10, "minimum": 1, "maximum": 100, "description": "参数2的描述" } } } \`\`\` ``` ### 4. 输出Schema (必需) ```markdown ## 输出Schema \`\`\`json { "type": "object", "required": ["result"], "properties": { "result": { "type": "string", "description": "处理结果" }, "metadata": { "type": "object", "description": "元数据信息" } } } \`\`\` ``` ### 5. 实现要求 (必需) ```markdown ## 实现要求 1. **技术栈**: Python 3.12+, FastAPI, uvicorn, httpx, pillow 2. **API端点**: - GET `/health` - 健康检查 (必需) - POST `/process` - 主要业务逻辑 3. **错误处理**: 参数验证、异常捕获、超时处理 4. **日志**: 记录关键操作和错误 5. **环境**: 使用 uv 或 Docker 6. **端口**: 默认8000,支持 `--port` 参数 ``` ### 6. 注册参数 (CodingAgent自动处理) 这些参数由 CodingAgent 在注册时自动填写: | 参数 | 类型 | 说明 | 示例 | |------|------|------|------| | `tool_id` | string | 工具唯一标识 | `"image_stitcher"` | | `name` | string | 工具显示名称 | `"图片拼接工具"` | | `description` | string | 功能描述 | `"将多张图片拼接成一张"` | | `category` | string | 工具分类 | `"cv"`, `"ai"`, `"nlp"` | | `runtime_type` | string | 运行环境 | `"local"` 或 `"docker"` | | `internal_port` | integer | 服务端口 | `8001` | | `endpoint_path` | string | API路径 | `"/stitch"` | | `http_method` | string | HTTP方法 | `"POST"` | | `input_schema` | object | 输入JSON Schema | 见上文 | | `output_schema` | object | 输出JSON Schema | 见上文 | | `host_dir` | string | 本地目录 (local) | `"tools/local/image_stitcher"` | | `container_id` | string | 容器ID (docker) | `"abc123..."` | | `stream_support` | boolean | 是否支持流式输出 | `false` | | `group_ids` | array | 所属工具组 | `["image_processing"]` | | `tool_slug_ids` | array | 工具标签 | `["comfyui", "stable-diffusion"]` | --- ## 任务书模板 ```markdown # {工具名称}任务书 ## 工具标识 - **tool_id**: `tool_name_here` - **工具名称**: 工具显示名称 - **工具描述**: 一句话描述工具功能 - **分类**: cv / ai / nlp / audio ## 功能需求 ### 功能1: 功能名称 - 详细描述功能1 - 输入要求 - 输出格式 ### 功能2: 功能名称 - 详细描述功能2 ## 输入Schema \`\`\`json { "type": "object", "required": ["必需参数1", "必需参数2"], "properties": { "param1": { "type": "string", "description": "参数描述" }, "param2": { "type": "integer", "default": 10, "description": "参数描述" } } } \`\`\` ## 输出Schema \`\`\`json { "type": "object", "required": ["result"], "properties": { "result": { "type": "string", "description": "结果描述" } } } \`\`\` ## 实现要求 1. **技术栈**: Python 3.12+, FastAPI, uvicorn, {其他依赖} 2. **API端点**: - GET `/health` - 健康检查 - POST `/{endpoint}` - 主要业务逻辑 3. **错误处理**: 参数验证、异常捕获 4. **日志**: 记录关键操作 5. **环境**: uv (简单项目) 或 Docker (复杂项目) 6. **端口**: 默认8000, 支持 `--port` 参数 ## 参考资料 (可选) - API文档链接 - GitHub仓库 - 示例代码 ## 特殊要求 (可选) - 性能要求 - 安全要求 - 其他约束 ``` --- ## JSON Schema 编写规范 ### 基本类型 ```json { "string_param": { "type": "string", "description": "字符串参数" }, "integer_param": { "type": "integer", "description": "整数参数" }, "number_param": { "type": "number", "description": "数字参数(含小数)" }, "boolean_param": { "type": "boolean", "description": "布尔参数" } } ``` ### 枚举类型 ```json { "direction": { "type": "string", "enum": ["horizontal", "vertical", "grid"], "default": "horizontal", "description": "拼接方向: horizontal(水平), vertical(垂直), grid(网格)" } } ``` ### 数值约束 ```json { "count": { "type": "integer", "default": 1, "minimum": 1, "maximum": 10, "description": "生成数量,范围1-10" }, "temperature": { "type": "number", "default": 0.7, "minimum": 0.0, "maximum": 2.0, "description": "温度参数" } } ``` ### 数组类型 ```json { "images": { "type": "array", "items": { "type": "string" }, "minItems": 2, "description": "图片列表,至少2张" }, "tags": { "type": "array", "items": { "type": "string" }, "description": "标签列表" } } ``` ### 对象数组 ```json { "files": { "type": "array", "items": { "type": "object", "required": ["filename", "content"], "properties": { "filename": { "type": "string", "description": "文件名" }, "content": { "type": "string", "description": "文件内容(Base64编码)" }, "type": { "type": "string", "description": "文件类型" } } }, "description": "文件列表" } } ``` ### 嵌套对象 ```json { "config": { "type": "object", "properties": { "width": { "type": "integer", "default": 512 }, "height": { "type": "integer", "default": 512 }, "quality": { "type": "string", "enum": ["low", "medium", "high"], "default": "medium" } }, "description": "配置参数" } } ``` ### 字符串格式验证 ```json { "email": { "type": "string", "format": "email", "description": "邮箱地址" }, "url": { "type": "string", "format": "uri", "description": "URL地址" }, "tool_id": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$", "description": "工具ID,只能包含小写字母、数字和下划线" } } ``` ### 必需参数 vs 可选参数 ```json { "type": "object", "required": ["prompt", "model"], // 只列出真正必需的参数 "properties": { "prompt": { "type": "string", "description": "生成提示词(必需)" }, "model": { "type": "string", "description": "模型名称(必需)" }, "steps": { "type": "integer", "default": 20, "description": "生成步数(可选,默认20)" } } } ``` --- ## 提交任务 ### 方式1: 使用提交脚本 1. 将任务书保存到 `task_specs/` 目录,例如 `task_specs/my_tool_task.md` 2. 创建提交脚本 `scripts/submit_my_tool.py`: ```python #!/usr/bin/env python3 import asyncio from pathlib import Path from tool_agent.tool.agent import CodingAgent async def main(): # 读取任务书 task_spec_path = Path(__file__).parent.parent / "task_specs" / "my_tool_task.md" task_spec = task_spec_path.read_text(encoding="utf-8") # 创建CodingAgent实例 agent = CodingAgent() print("🚀 提交工具封装任务...") print(f"📄 任务书: {task_spec_path}") print("-" * 60) # 执行任务 result = await agent.execute( task_spec=task_spec, reference_files=[] ) print("-" * 60) print("✅ 任务完成!") print(f"📊 结果: {result}") if __name__ == "__main__": asyncio.run(main()) ``` 3. 运行脚本: ```bash cd C:\Users\11304\gitlab\cybertogether\tool_agent python scripts/submit_my_tool.py ``` ### 方式2: 通过 RouterAgent 提交 ```python from tool_agent.router.router_agent import RouterAgent router = RouterAgent() result = await router.submit_task(task_spec="任务书内容...") ``` ### 方式3: 通过 ServiceAgent 提交 ```python from tool_agent.service.agent import ServiceAgent service = ServiceAgent() result = await service.submit_task(task_spec="任务书内容...") ``` --- ## 常见问题 ### Q1: tool_id 命名规则是什么? **A**: 必须符合正则表达式 `^[a-z][a-z0-9_]*$`: - ✅ 正确: `image_stitcher`, `comfyui_launcher`, `text2video` - ❌ 错误: `ImageStitcher` (大写), `image-stitcher` (连字符), `123tool` (数字开头) ### Q2: 什么时候用 uv,什么时候用 Docker? **A**: - **使用 uv**: 纯Python项目 + 简单依赖(pip可安装) - **使用 Docker**: 需要系统库、GPU、端口映射、复杂环境配置 ### Q3: 输入/输出 Schema 必须完全匹配实际API吗? **A**: 是的。Schema 用于: 1. 参数验证 (Pydantic模型) 2. 自动生成API文档 3. RouterAgent 理解工具能力 ### Q4: 如何处理文件上传? **A**: 推荐使用 Base64 编码: ```json { "image": { "type": "string", "description": "图片内容(Base64编码)" } } ``` 或使用文件对象数组: ```json { "files": { "type": "array", "items": { "type": "object", "properties": { "filename": {"type": "string"}, "content": {"type": "string", "description": "Base64编码"} } } } } ``` ### Q5: 工具创建失败怎么办? **A**: CodingAgent 会自动: 1. 诊断错误原因 2. 尝试修复代码 3. 重新测试 如果多次失败,检查: - 任务书是否清晰明确 - 依赖是否可安装 - API文档是否正确 ### Q6: 如何测试已注册的工具? **A**: 工具注册后会自动启动HTTP服务,可以通过: ```bash # 查看工具列表 curl http://localhost:8080/tools # 调用工具 curl -X POST http://localhost:8080/invoke \ -H "Content-Type: application/json" \ -d '{ "tool_id": "your_tool_id", "parameters": {...} }' ``` ### Q7: 可以更新已存在的工具吗? **A**: 可以。重新提交任务书,使用相同的 `tool_id`,CodingAgent 会: 1. 检测到已存在的工具 2. 更新代码和配置 3. 重新注册元数据 ### Q8: 如何添加工具到工具组? **A**: 在任务书中指定: ```markdown ## 工具标识 - **tool_id**: `my_tool` - **工具组**: `image_processing` - **工具标签**: `["stable-diffusion", "comfyui"]` ``` 或在注册时指定: ```python register_tool( tool_id="my_tool", group_ids=["image_processing"], tool_slug_ids=["stable-diffusion", "comfyui"] ) ``` --- ## 项目结构说明 工具创建后的标准结构: ``` tools/local/{tool_id}/ ├── pyproject.toml # 项目元数据和依赖 ├── main.py # FastAPI HTTP服务入口 │ ├── @app.get("/health") # 健康检查(必需) │ └── @app.post("/{endpoint}") # 业务逻辑端点 ├── {core_module}.py # 核心业务逻辑 └── tests/ ├── test_basic.py # 单元测试 └── output/ # 测试输出文件 ``` ### main.py 示例 ```python from fastapi import FastAPI, HTTPException from pydantic import BaseModel import uvicorn import argparse app = FastAPI() class InputModel(BaseModel): param1: str param2: int = 10 class OutputModel(BaseModel): result: str @app.get("/health") async def health(): return {"status": "ok"} @app.post("/process") async def process(input_data: InputModel) -> OutputModel: try: # 调用核心业务逻辑 result = do_something(input_data.param1, input_data.param2) return OutputModel(result=result) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--port", type=int, default=8000) args = parser.parse_args() uvicorn.run(app, host="0.0.0.0", port=args.port) ``` --- ## 示例任务书 参考 `task_specs/kuaishou_kling_task.md` 查看完整示例。 --- ## 联系与支持 - 项目仓库: `tool_agent/` - 任务书目录: `task_specs/` - 提交脚本目录: `scripts/` - 工具注册表: `data/registry.json`