# LiteLLM 和 Agent Manager 回调接口文档 ## 概述 本文档描述了 mcp-server 接收 LiteLLM 和 Agent Manager 服务的回调接口规范,包括请求体格式、响应体格式以及处理逻辑。 --- ## 1. LiteLLM 回调接口 ### 1.1 接口信息 - **接口路径**: `/api/v1/billing/litellm-callback` - **请求方法**: `POST` - **Content-Type**: `application/json` - **功能**: 接收 LiteLLM 的实时 Token 计费数据,支持单个对象或批量数组格式 ### 1.2 请求体格式 #### 1.2.1 单个对象格式 ```json { "id": "call-abc123", // 必填:调用ID(别名:call_id) "trace_id": "trace-xyz789", // 可选:追踪ID "model": "gpt-4", // 必填:模型名称 "call_type": "completion", // 可选:调用类型 "cache_hit": false, // 可选:是否缓存命中 "stream": false, // 可选:是否流式响应 "status": "success", // 可选:状态(默认:success) "custom_llm_provider": "openai", // 可选:LLM提供商 "startTime": "2026-01-11T10:00:00Z", // 可选:开始时间(ISO 8601 或 Unix 时间戳) "endTime": "2026-01-11T10:00:05Z", // 可选:结束时间(ISO 8601 或 Unix 时间戳) "response_time": 5.2, // 可选:响应时间(秒) "response_cost": 0.001, // 可选:响应成本(美元) "total_tokens": 1500, // 可选:总Token数 "prompt_tokens": 1000, // 可选:Prompt Token数 "completion_tokens": 500, // 可选:Completion Token数 "api_key": "sk-xxx", // 可选:API密钥 "team_id": "team-123", // 可选:团队ID "api_base": "https://api.openai.com", // 可选:API基础URL "model_group": "gpt-4", // 可选:模型组 "model_id": "gpt-4-0613", // 可选:模型ID "messages": [ // 可选:消息列表 { "role": "user", "content": "Hello" } ], "response": { // 可选:响应内容 "choices": [...] }, "metadata": { // 可选:元数据(重要:包含租户信息) "user_api_key_hash": "hash-xxx", // API密钥哈希 "user_api_key_team_id": "team-123", // 团队ID "user_api_key_auth_metadata": { // 租户认证元数据(优先使用) "tenant_id": "tenant-123", "channel_id": "channel-456", "tenant_name": "租户名称" }, "usage_object": { // Token使用量对象 "total_tokens": 1500, "prompt_tokens": 1000, "completion_tokens": 500 } }, "hidden_params": {}, // 可选:隐藏参数 "model_map_information": {}, // 可选:模型映射信息 "cost_breakdown": {}, // 可选:成本明细 "error_str": null, // 可选:错误信息 "error_information": {} // 可选:错误详情 } ``` #### 1.2.2 批量数组格式 ```json [ { "id": "call-abc123", "model": "gpt-4", "total_tokens": 1500, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } }, { "id": "call-xyz789", "model": "gpt-3.5-turbo", "total_tokens": 800, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } } ] ``` #### 1.2.3 字段说明 | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|------| | `id` / `call_id` | string | 是 | 调用唯一标识符,用于幂等性检查 | | `trace_id` | string | 否 | 追踪ID,当 `id` 不存在时作为备用 | | `model` | string | 是 | 模型名称(如:gpt-4, gpt-3.5-turbo) | | `total_tokens` | integer | 否 | 总Token数,用于计算EU消耗 | | `prompt_tokens` | integer | 否 | Prompt Token数 | | `completion_tokens` | integer | 否 | Completion Token数 | | `startTime` | string/float | 否 | 开始时间(ISO 8601 字符串或 Unix 时间戳) | | `endTime` | string/float | 否 | 结束时间(ISO 8601 字符串或 Unix 时间戳) | | `response_cost` | float | 否 | 响应成本(美元) | | `metadata` | object | 否 | 元数据对象,包含租户信息 | | `metadata.user_api_key_hash` | string | 否 | API密钥哈希值 | | `metadata.user_api_key_team_id` | string | 否 | 团队ID | | `metadata.user_api_key_auth_metadata` | object | 否 | **优先使用**:租户认证元数据 | | `metadata.user_api_key_auth_metadata.tenant_id` | string | 否 | 租户ID | | `metadata.user_api_key_auth_metadata.channel_id` | string | 否 | 渠道ID | | `metadata.usage_object` | object | 否 | Token使用量对象(备用) | ### 1.3 响应体格式 #### 1.3.1 单个对象响应 ```json { "message": "Success", "call_id": "call-abc123", "record_id": "550e8400-e29b-41d4-a716-446655440000", "eu_consumed": 0.15, "balance_updated": true } ``` #### 1.3.2 批量数组响应 ```json { "message": "Batch processed", "count": 2, "results": [ { "message": "Success", "call_id": "call-abc123", "record_id": "550e8400-e29b-41d4-a716-446655440000", "eu_consumed": 0.15, "balance_updated": true }, { "message": "Success", "call_id": "call-xyz789", "record_id": "550e8400-e29b-41d4-a716-446655440001", "eu_consumed": 0.08, "balance_updated": true } ] } ``` #### 1.3.3 错误响应 ```json { "detail": "无法解析租户ID" } ``` **HTTP 状态码**: - `200`: 成功处理 - `400`: 请求参数错误(如无法解析租户ID) - `500`: 服务器内部错误 #### 1.3.4 响应字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | `message` | string | 处理结果消息("Success" / "Already processed" / "Skipped - no call_id") | | `call_id` | string | 调用ID | | `record_id` | string | 计费记录ID(UUID) | | `eu_consumed` | float | 消耗的EU数量 | | `balance_updated` | boolean | 是否成功更新余额 | ### 1.4 处理逻辑 1. **幂等性检查**: 根据 `call_id` 检查是否已处理过,避免重复计费 2. **租户信息解析**: - 优先从 `metadata.user_api_key_auth_metadata` 获取租户信息 - 如果不存在,则通过 `metadata.user_api_key_hash` 从数据库查询 3. **Token计算**: - 优先使用顶级字段 `total_tokens`、`prompt_tokens`、`completion_tokens` - 如果不存在,从 `metadata.usage_object` 获取 4. **EU计算**: 根据模型类型和Token数量计算EU消耗 - GPT-4: 0.0001 EU/token - GPT-3.5-turbo: 0.00005 EU/token - 默认: 0.0001 EU/token 5. **余额扣减**: 使用数据库行锁确保并发安全,原子性更新用户余额 6. **计费记录**: 创建 `ModelBillingRecord` 记录,保存完整的回调数据 ### 1.5 健康检查接口 - **接口路径**: `/api/v1/billing/litellm-callback/health` - **请求方法**: `GET` - **响应**: ```json { "status": "ok", "endpoint": "/api/v1/billing/litellm-callback" } ``` --- ## 2. Agent Manager 回调接口 ### 2.1 接口信息 - **接口路径**: `/api/v1/billing/agent-callback` - **请求方法**: `POST` - **Content-Type**: `application/json` - **功能**: 接收 Agent Manager 的 Agent 运行时信息,用于记录运行时长并计费 ### 2.2 请求体格式 ```json { "agentName": "taiji-assistant-abc123", // 必填:Agent 名称 "userId": "user-123-456", // 必填:用户 ID "podRunningTimeSeconds": 120, // 必填:Pod 运行时间(秒),即 VM 运行时间 "toolsUsed": [ // 可选:使用的工具列表 "web_search", "calculator", "file_reader" ], "startTime": "2026-01-11T10:00:00Z", // 可选:开始时间(ISO 8601 格式) "endTime": "2026-01-11T10:02:00Z", // 可选:结束时间(ISO 8601 格式) "requestId": "req-abc-123" // 可选:请求 ID } ``` ### 2.3 请求字段说明 | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|------| | `agentName` | string | 是 | Agent 名称,用于标识具体的 Agent 实例 | | `userId` | string | 是 | 用户 ID,必须是系统中存在的用户 | | `podRunningTimeSeconds` | integer | 是 | Pod 运行时间(秒),即 VM 实际运行时长,用于计费 | | `toolsUsed` | array[string] | 否 | 使用的工具列表,用于记录 Agent 调用的工具 | | `startTime` | string | 否 | 开始时间,ISO 8601 格式(如:2026-01-11T10:00:00Z) | | `endTime` | string | 否 | 结束时间,ISO 8601 格式(如:2026-01-11T10:02:00Z) | | `requestId` | string | 否 | 请求 ID,用于追踪和关联请求 | ### 2.4 响应体格式 #### 2.4.1 成功响应 ```json { "success": true, "message": "Agent 计费记录创建成功", "recordId": "550e8400-e29b-41d4-a716-446655440000" } ``` #### 2.4.2 错误响应 **用户不存在**: ```json { "detail": "用户不存在: user-123-456" } ``` HTTP 状态码: `404` **服务器错误**: ```json { "detail": "回调处理失败: [错误详情]" } ``` HTTP 状态码: `500` #### 2.4.3 响应字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | `success` | boolean | 是否成功处理 | | `message` | string | 处理结果消息 | | `recordId` | string | 创建的计费记录ID(UUID),失败时为 null | ### 2.5 处理逻辑 1. **用户验证**: 验证 `userId` 是否存在,不存在则返回 404 错误 2. **时间解析**: 解析 `startTime` 和 `endTime`(ISO 8601 格式),转换为 UTC 时间 3. **成本计算**: - 根据 `podRunningTimeSeconds` 计算 EU 消耗 - 根据 Agent 类型和运行时长计算成本(平台 Agent 使用 `calculate_platform_agent_cost`) 4. **计费记录**: 创建 `AgentBillingRecord` 记录,包含: - 用户ID、渠道ID - Agent 名称、类型 - 运行时长、EU消耗、成本 - 开始时间、结束时间 - 使用的工具列表 - 请求ID 5. **余额扣减**: 调用 `deduct_balance` 扣除用户余额 6. **事务提交**: 所有操作在数据库事务中执行,失败时回滚 ### 2.6 健康检查接口 - **接口路径**: `/api/v1/billing/agent-callback/health` - **请求方法**: `GET` - **响应**: ```json { "status": "ok", "endpoint": "/api/v1/billing/agent-callback" } ``` --- ## 3. 通用说明 ### 3.1 认证 目前两个回调接口均未实现认证机制,建议在生产环境中添加: - API Key 认证 - IP 白名单 - 签名验证 ### 3.2 幂等性 - **LiteLLM 回调**: 通过 `call_id` 实现幂等性,相同 `call_id` 的请求只会处理一次 - **Agent Manager 回调**: 目前未实现幂等性,建议添加 `requestId` 的唯一性检查 ### 3.3 错误处理 - 所有错误都会记录到日志中 - 数据库操作失败时会自动回滚事务 - 返回适当的 HTTP 状态码和错误信息 ### 3.4 性能考虑 - LiteLLM 回调支持批量处理,提高吞吐量 - 使用数据库行锁确保并发安全 - 余额更新使用原子操作 ### 3.5 数据存储 - **LiteLLM 回调**: 数据存储在 `ModelBillingRecord` 表中 - **Agent Manager 回调**: 数据存储在 `AgentBillingRecord` 表中 - 所有回调的原始数据都会保存,便于后续审计和分析 --- ## 4. 示例代码 ### 4.1 LiteLLM 回调示例(cURL) ```bash # 单个对象 curl -X POST http://mcp-server:8002/api/v1/billing/litellm-callback \ -H "Content-Type: application/json" \ -d '{ "id": "call-abc123", "model": "gpt-4", "total_tokens": 1500, "prompt_tokens": 1000, "completion_tokens": 500, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } }' # 批量数组 curl -X POST http://mcp-server:8002/api/v1/billing/litellm-callback \ -H "Content-Type: application/json" \ -d '[ { "id": "call-abc123", "model": "gpt-4", "total_tokens": 1500, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } }, { "id": "call-xyz789", "model": "gpt-3.5-turbo", "total_tokens": 800, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } } ]' ``` ### 4.2 Agent Manager 回调示例(cURL) ```bash curl -X POST http://mcp-server:8002/api/v1/billing/agent-callback \ -H "Content-Type: application/json" \ -d '{ "agentName": "taiji-assistant-abc123", "userId": "user-123-456", "podRunningTimeSeconds": 120, "toolsUsed": ["web_search", "calculator"], "startTime": "2026-01-11T10:00:00Z", "endTime": "2026-01-11T10:02:00Z", "requestId": "req-abc-123" }' ``` ### 4.3 Python 示例 ```python import requests # LiteLLM 回调 litellm_data = { "id": "call-abc123", "model": "gpt-4", "total_tokens": 1500, "metadata": { "user_api_key_auth_metadata": { "tenant_id": "tenant-123", "channel_id": "channel-456" } } } response = requests.post( "http://mcp-server:8002/api/v1/billing/litellm-callback", json=litellm_data ) print(response.json()) # Agent Manager 回调 agent_data = { "agentName": "taiji-assistant-abc123", "userId": "user-123-456", "podRunningTimeSeconds": 120, "toolsUsed": ["web_search", "calculator"], "startTime": "2026-01-11T10:00:00Z", "endTime": "2026-01-11T10:02:00Z", "requestId": "req-abc-123" } response = requests.post( "http://mcp-server:8002/api/v1/billing/agent-callback", json=agent_data ) print(response.json()) ``` --- ## 5. 配置说明 ### 5.1 LiteLLM 配置 在 LiteLLM 配置文件中设置回调地址: ```yaml general_settings: success_callback: ["webhook"] failure_callback: ["webhook"] webhook_url: "http://mcp-server:8002/api/v1/billing/litellm-callback" webhook_headers: Content-Type: "application/json" ``` ### 5.2 Agent Manager 配置 Agent Manager 需要在 Agent 运行结束后调用回调接口,配置回调地址: ``` CALLBACK_URL=http://mcp-server:8002/api/v1/billing/agent-callback ``` --- ## 6. 注意事项 1. **时间格式**: - LiteLLM 回调支持 ISO 8601 字符串和 Unix 时间戳 - Agent Manager 回调仅支持 ISO 8601 格式 2. **租户信息**: - LiteLLM 回调优先从 `metadata.user_api_key_auth_metadata` 获取租户信息 - 如果不存在,会尝试从数据库查询,但可能失败 3. **Token 计算**: - 优先使用顶级字段,其次使用 `metadata.usage_object` - 如果都不存在,Token 数默认为 0 4. **并发安全**: - 使用数据库行锁确保余额更新的原子性 - 建议在生产环境中使用连接池和适当的并发控制 5. **日志记录**: - 所有回调都会记录详细日志 - 建议配置日志轮转和监控告警 --- ## 7. 更新日志 - **2026-01-11**: 初始版本,包含 LiteLLM 和 Agent Manager 回调接口文档