From 1b49887819d01d77e3aac13669f55cc2abe4e33c Mon Sep 17 00:00:00 2001 From: elipitc Date: Mon, 1 Jun 2026 23:10:33 +0800 Subject: [PATCH] Sync sub-mode runtime docs and k8s updates --- .DS_Store | Bin 10244 -> 10244 bytes agent_templates/.DS_Store | Bin 10244 -> 10244 bytes agent_templates/agents/.DS_Store | Bin 10244 -> 10244 bytes api/agnet/deployments.py | 8 +- api/agnet/models.py | 4 +- api/swarm/callback_client.py | 2 +- api/swarm/orchestrator.py | 138 +++++- api/swarm/router.py | 1 + config/settings.py | 2 +- deploy-heicode.sh | 2 +- docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md | 36 +- docs/HEICODE_API_INTEGRATION.md | 132 ++--- docs/HEICODE_IMPLEMENTATION_STATUS.md | 46 +- docs/HEICODE_SUB_MODE_RUNTIME_INTEGRATION.md | 483 ++++++++++--------- docs/HEICODE_V2_1_4_UPDATE_SUMMARY.md | 30 +- k8s/agent-manager-deployment.yaml | 2 +- k8s/deployment-with-kubeconfig.yaml | 2 +- k8s/deployment.yaml | 2 +- k8s_manager.py | 5 +- 19 files changed, 511 insertions(+), 384 deletions(-) diff --git a/.DS_Store b/.DS_Store index 872d83d2e9893f541fb201ca6f6f06e37c1fecc8..45cbcb44b531efbd049c8d7aca73cb91e2c34096 100644 GIT binary patch delta 301 zcmZn(XbIS`ik(F+=+Ljp>)7=;j;>|zmw$HL5y(;8%*yeChlQhfMakrkB1#;)&T&Je zK8i>PrMM*JvOFdz$yO^z1jVdhjR*qkNm%^cS<#R#Z?g+Y%YogtHS16wz_3|Zayk=MhpQmD4#_`ClWk;pn3ePuCVR_# Q!r^S$%j`I0L}xJp0C*W?8UO$Q delta 301 zcmZn(XbIS`ik(H-HNRu>I(9vdebIgQ&+k3%2;?YkX61On!@^&_dEexZB1#;UKd)UD zJOGsXC?X-0;*yk;pTxkxfGjLFIa-v5S>XDI%~_(}%yCr?K|lp840;Ud44Diix%n<| zP2m%zYroz(?uaUnFch17L55*)a(-?BP!9vc>VVC{lGB;6I$Qm4e U!enomPdJ<{dzl@FjOZ*T0M%k`r2qf` diff --git a/agent_templates/.DS_Store b/agent_templates/.DS_Store index e25a90474a178bd71f823392f871fc073a380f17..bd0c14a08731d1087c92f291304ed37a23555d6e 100644 GIT binary patch delta 80 zcmZn(XbIR*Bgn$KO`3o5MG@i6lLb}S*!Yfc^vge+yjNTf#(XF)$IRA}u$f6>D?dyO LRhktj&AE^KC!*vbzR MLzQL)N;5D308|wr&j0`b diff --git a/agent_templates/agents/.DS_Store b/agent_templates/agents/.DS_Store index 1122b510a7302f3ed2567f3e26d40517f8f4afad..ac52fbd3b0e7daf3263849b6f36d40cac7bcae09 100644 GIT binary patch delta 51 zcmZn(XbIS$E5X9@Cw$6eLkSJGoI9NT^3Nv6OK8EE{SsQtti=u+6TR6tvn%{%2LRn2 B5&QrE delta 50 zcmZn(XbIS$E5X9~-u32WLkSJGCb{dE1rJP)m(YSS`z5rPxNdAr^kLu3uJD%~0O08o Ay#N3J diff --git a/api/agnet/deployments.py b/api/agnet/deployments.py index de9097c..1007b1a 100644 --- a/api/agnet/deployments.py +++ b/api/agnet/deployments.py @@ -220,11 +220,11 @@ async def emit_sub_mode_lifecycle_callbacks( ) -def get_agnet_namespace(user_id: str, binding_scope: str) -> str: - """Generate namespace for Heicode deployments.""" +def get_agent_namespace(user_id: str, binding_scope: str) -> str: + """Generate namespace for Heicode agent deployments.""" combined = f"{user_id}:{binding_scope}" hash_suffix = hashlib.sha256(combined.encode()).hexdigest()[:6] - namespace = f"agnet-{user_id}-{hash_suffix}"[:63] + namespace = f"agent-{user_id}-{hash_suffix}"[:63] return namespace.lower().replace("_", "-") @@ -399,7 +399,7 @@ async def create_deployment( user_id = user_id or plan_user_context.get("user_id") or "default" binding_scope = binding_scope or plan_user_context.get("binding_scope") or f"task-{plan_summary.get('intent_id') or deployment_id}" correlation_id = correlation_id or request.metadata.get("correlation_id") - namespace = get_agnet_namespace(user_id, binding_scope) + namespace = get_agent_namespace(user_id, binding_scope) # Create deployment record deployment = Deployment( diff --git a/api/agnet/models.py b/api/agnet/models.py index f116bbc..f0b1e0f 100644 --- a/api/agnet/models.py +++ b/api/agnet/models.py @@ -175,7 +175,7 @@ class ResourceGrant(BaseModel): class CallbackConfig(BaseModel): - """Callback configuration for Agnet -> Heicode event delivery.""" + """Callback configuration for Agent Runtime -> Heicode event delivery.""" url: str = Field(..., description="HTTPS callback endpoint") signing_secret_ref: str = Field(..., description="Vault path to callback signing secret") subscribed_events: List[str] = Field( @@ -209,7 +209,7 @@ class CreateDeploymentRequest(BaseModel): budget: Optional[BudgetConfig] = Field(None, description="Budget configuration") billing_context: Optional[BillingContext] = Field(None, description="Billing and model gateway config") resource_grants: List[ResourceGrant] = Field(default_factory=list, description="Resource grants") - callback: Optional[CallbackConfig] = Field(None, description="Agnet -> Heicode callback configuration") + callback: Optional[CallbackConfig] = Field(None, description="Agent Runtime -> Heicode callback configuration") agile_context: Optional[Dict[str, Any]] = Field(None, description="Heicode sub-mode agile context") sub_mode: Optional[str] = Field(None, description="Heicode sub mode: agile or waterfall") metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata") diff --git a/api/swarm/callback_client.py b/api/swarm/callback_client.py index 2d58355..8355cf3 100644 --- a/api/swarm/callback_client.py +++ b/api/swarm/callback_client.py @@ -40,7 +40,7 @@ def _utc_iso() -> str: def _env_name_from_secret_ref(secret_ref: str) -> str: - """Map azkv secret names to ENV names, e.g. agnet-callback-key.""" + """Map azkv secret names to ENV names, e.g. agent-callback-key.""" secret_name = secret_ref.rstrip("/").split("/")[-1] return secret_name.upper().replace("-", "_") diff --git a/api/swarm/orchestrator.py b/api/swarm/orchestrator.py index 62a2bad..591c77d 100644 --- a/api/swarm/orchestrator.py +++ b/api/swarm/orchestrator.py @@ -464,26 +464,78 @@ class SwarmOrchestrator: error = response.get("error") or {} message_text = error.get("message") if isinstance(error, dict) else str(error) error_data = error.get("data") if isinstance(error, dict) else {} - if isinstance(error_data, dict): - error_message = SwarmMessage( + + if self._is_retryable_runtime_error(message_text or "") and agent_record: + retry_task = self._build_retry_task(agent_record, task, message_text or "gateway timeout") + retry_message = SwarmMessage( message_id=str(uuid.uuid4()), swarm_id=self.swarm_id, - from_agent_id=client.agent_id, - to_agent_id=None, - message_type="error", - content=message_text or "A2A agent returned an error response", + from_agent_id=None, + to_agent_id=client.agent_id, + message_type="task_retry", + content=retry_task, message_metadata={ - "newapi_request_id": error_data.get("request_id"), - "model_status_code": error_data.get("status_code"), - "model_response_preview": (error_data.get("response_text") or "")[:1000], + "retry_reason": message_text, + "retryable": True, }, ) - self.db.add(error_message) + self.db.add(retry_message) self.db.commit() - runtime_error = RuntimeError(message_text or "A2A agent returned an error response") - if isinstance(error_data, dict): - setattr(runtime_error, "request_id", error_data.get("request_id")) - raise runtime_error + self.swarm.total_messages += 1 + agent_record.current_task = retry_task + self.db.commit() + await self._emit_tool_event( + "sk_tool.called", + client.agent_id, + { + "tool_name": "agent_task_retry", + "tool_invocation_id": retry_message.message_id, + "summary": "Retrying agent task with a reduced output contract", + "arguments_redacted": True, + }, + ) + response = await client.send_message({"text": retry_task}) + if not (isinstance(response, dict) and response.get("error")): + usage = self._extract_usage(response) + model_metadata = self._extract_model_metadata(response) + await self._emit_tool_event( + "sk_tool.completed", + client.agent_id, + { + "tool_name": "agent_task_retry", + "tool_invocation_id": retry_message.message_id, + "summary": "Agent retry task completed", + "result_preview": str(response)[:500], + "model_usage": usage, + "newapi_request_id": model_metadata.get("newapi_request_id"), + "model_api_format": model_metadata.get("api_format"), + }, + ) + + if isinstance(response, dict) and response.get("error"): + error = response.get("error") or {} + message_text = error.get("message") if isinstance(error, dict) else str(error) + error_data = error.get("data") if isinstance(error, dict) else {} + if isinstance(error_data, dict): + error_message = SwarmMessage( + message_id=str(uuid.uuid4()), + swarm_id=self.swarm_id, + from_agent_id=client.agent_id, + to_agent_id=None, + message_type="error", + content=message_text or "A2A agent returned an error response", + message_metadata={ + "newapi_request_id": error_data.get("request_id"), + "model_status_code": error_data.get("status_code"), + "model_response_preview": (error_data.get("response_text") or "")[:1000], + }, + ) + self.db.add(error_message) + self.db.commit() + runtime_error = RuntimeError(message_text or "A2A agent returned an error response") + if isinstance(error_data, dict): + setattr(runtime_error, "request_id", error_data.get("request_id")) + raise runtime_error usage = self._extract_usage(response) model_metadata = self._extract_model_metadata(response) if self.swarm and usage["total_tokens"]: @@ -812,8 +864,63 @@ class SwarmOrchestrator: "Agile context: " + json.dumps(project_context["agile_context"], ensure_ascii=False, sort_keys=True) ) + prompt_parts.append(self._role_output_contract(agent.role)) return "\n".join(prompt_parts) + def _role_output_contract(self, role: Optional[str]) -> str: + """Return a compact output contract tuned for runtime stability.""" + normalized_role = (role or "worker").lower() + common = ( + "Output contract: keep the response concise and implementation-oriented. " + "Prefer a minimal viable skeleton over a full project. " + "Do not exceed 12 bullets. Do not exceed 120 lines of code total." + ) + role_contracts = { + "backend": ( + "Return only: 1) a short API/data-model summary, " + "2) one compact Python/FastAPI code skeleton, " + "3) a brief test checklist." + ), + "frontend": ( + "Return only: 1) a short UI/component summary, " + "2) one compact React/JSX/CSS skeleton, " + "3) a brief interaction checklist." + ), + "reviewer": ( + "Return only: 1) major risks, 2) test cases, 3) release/blocking notes. " + "No long prose and no large code blocks." + ), + "architect": ( + "Return only: 1) architecture outline, 2) core modules, 3) key interfaces. " + "No large code blocks." + ), + } + fallback = "Return a short implementation summary and one minimal code skeleton if needed." + return f"{common} {role_contracts.get(normalized_role, fallback)}" + + def _build_retry_task(self, agent: Optional[SwarmAgent], original_task: str, error: str) -> str: + """Build a smaller retry prompt when the first generation overloads the model gateway.""" + role = agent.role if agent else "worker" + retry_instructions = ( + "Previous attempt failed at the model gateway. Retry with a much smaller response. " + "Return only the single most important implementation skeleton for your role. " + "Limit output to at most 6 bullets and at most 60 lines of code total. " + "Skip optional explanations, examples, and secondary files." + ) + return f"{original_task}\nRole: {role}\nRetry reason: {error}\n{retry_instructions}" + + def _is_retryable_runtime_error(self, message: str) -> bool: + """Classify model-gateway errors that benefit from a smaller retry.""" + normalized = (message or "").lower() + retry_markers = ( + "504 gateway time-out", + "504 gateway timeout", + "timed out", + "timeout", + "upstream request timeout", + ) + return any(marker in normalized for marker in retry_markers) + def _response_summary(self, response: Any) -> str: """Return a readable response summary for logs, artifacts, and callbacks.""" text = self._extract_deliverable_text(response) @@ -973,6 +1080,7 @@ class SwarmOrchestrator: "redacted": True, "agent_role": role, "runtime_deployment_id": self.swarm_id, + "summary_only": False, } if stored: metadata.update( @@ -1057,6 +1165,8 @@ class SwarmOrchestrator: "source": "agent-manager-sub-mode-runtime", "runtime_deployment_id": self.swarm_id, "agent_count": len(agents), + "synthesized": True, + "summary_only": True, } if stored: metadata.update( diff --git a/api/swarm/router.py b/api/swarm/router.py index 44fff53..d896f82 100644 --- a/api/swarm/router.py +++ b/api/swarm/router.py @@ -109,6 +109,7 @@ def _synthesized_artifacts_for_swarm(db: Session, swarm: Swarm) -> list[Dict[str "source": "agent-manager-sub-mode-runtime", "runtime_deployment_id": swarm.swarm_id, "synthesized": True, + "summary_only": True, "agent_count": len(agents), "content_hash": stored.content_hash if stored else None, "download_path": runtime_artifact_download_path(swarm.swarm_id, artifact_id), diff --git a/config/settings.py b/config/settings.py index f81d7b2..4a32851 100644 --- a/config/settings.py +++ b/config/settings.py @@ -17,7 +17,7 @@ class Settings(BaseSettings): IDEMPOTENCY_TTL_SECONDS: int = 86400 # 24 hours # Kubernetes - NAMESPACE_PREFIX: str = "agnet" + NAMESPACE_PREFIX: str = "agent" # Model gateways HEICODE_NEWAPI_BASE_URL: str = "https://code.xinghanlab.com/v1" diff --git a/deploy-heicode.sh b/deploy-heicode.sh index 6615831..120051b 100755 --- a/deploy-heicode.sh +++ b/deploy-heicode.sh @@ -37,5 +37,5 @@ echo "" echo "📝 Next steps:" echo " 1. Port forward: kubectl port-forward -n agent-manager svc/agent-manager 8000:80" echo " 2. Test health: curl http://localhost:8000/api/agent/health" -echo " 3. Compatibility health: curl http://localhost:8000/api/agnet/health" +echo " 3. Compatibility health (legacy): curl http://localhost:8000/api/agnet/health" echo "" diff --git a/docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md b/docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md index c383e74..a848515 100644 --- a/docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md +++ b/docs/HEICODE_AGNET_CALLBACK_CONTRACT_v1.md @@ -1,4 +1,4 @@ -# Agnet → Heicode Manager 反向 Callback 契约 v1(提案) +# Agent Runtime → Heicode Manager 反向 Callback 契约 v1(提案) > **状态**:DRAFT — 由 Heicode Manager 团队起草,发回给 Agent Manager 团队评审 > **配套阅读**:`HEICODE_API_INTEGRATION.md`(v2.0.0,正向:Heicode → Agent Manager) @@ -29,10 +29,10 @@ ### 1.1 正向(已实现,文档 v2.0.0) ``` -Heicode Manager ──POST /api/agnet/deployments──▶ Agent Manager - ──GET /api/agnet/.../logs────▶ - ──GET /api/agnet/.../events──▶ - ──GET /api/agnet/.../metrics─▶ +Heicode Manager ──POST /api/agent/sub-agile/deployments──▶ Agent Manager + ──GET /api/agent/.../logs────▶ + ──GET /api/agent/.../events──▶ + ──GET /api/agent/.../metrics─▶ ``` ### 1.2 反向(**未定义** — 本文要解决的) @@ -67,7 +67,7 @@ Heicode Manager ◀──??? Agent Manager 怎么告诉我们: │ │ │ 审批等事件触发 │ │ │ │ │ │ ③ 接收回调 │ ◀──POST {callback_url}───│ │ -│ /api/agnet │ 含 HMAC 签名 + │ │ +│ /api/agent │ 含 HMAC 签名 + │ │ │ /callback │ X-Agnet-Event-Id 幂等 │ │ │ │ │ │ │ ④ 200 OK 回执 │ ────────────────────────▶│ │ @@ -78,18 +78,18 @@ Heicode Manager ◀──??? Agent Manager 怎么告诉我们: --- -## 3. Heicode 侧注册(callback_url 怎么告诉 Agnet) +## 3. Heicode 侧注册(callback_url 怎么告诉 Agent Runtime) ### 3.1 创建部署时携带 -扩展 `POST /api/agnet/deployments` 请求体,新增可选字段: +扩展 `POST /api/agent/sub-agile/deployments` 请求体,新增可选字段: ```json { "orchestration_plan": "...", "agents": [ ... ], "callback": { - "url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key", "subscribed_events": [ "phase.changed", @@ -114,7 +114,7 @@ Heicode Manager ◀──??? Agent Manager 怎么告诉我们: ### 3.2 后绑定 / 修改(可选 P2 阶段) ``` -PATCH /api/agnet/deployments/{deployment_id}/callback +PATCH /api/agent/sub-agile/deployments/{deployment_id}/callback ``` 允许在部署运行期间更换 callback URL(例如 Heicode 灰度发布切换接收端)。 @@ -127,12 +127,12 @@ PATCH /api/agnet/deployments/{deployment_id}/callback | 方法 | URL | 说明 | |------|-----|------| -| `POST` | `{callback_url}` | Agnet 推送事件 | +| `POST` | `{callback_url}` | Agent Runtime 推送事件 | Heicode 生产端点(建议): ``` -POST https://code.xinghanlab.com/api/agnet/callbacks/swarm-events +POST https://code.xinghanlab.com/api/agent/callbacks/runtime-events ``` ### 4.2 必需 Headers @@ -405,7 +405,7 @@ HTTP/1.1 400 Bad Request **Heicode 拿到这个事件后做什么**: 1. 推到桌面客户端的审批 UI(已有契约) 2. 用户点同意 / 拒绝 -3. Heicode 调正向接口:`POST /api/agnet/deployments/{id}/approvals/{approval_id}` body `{ "decision": "granted" | "rejected", "reason": "..." }` +3. Heicode 调正向接口:`POST /api/agent/sub-agile/deployments/{id}/approvals/{approval_id}` body `{ "decision": "granted" | "rejected", "reason": "..." }` ### 5.6 `approval.granted` / 5.7 `approval.rejected` @@ -521,11 +521,11 @@ stopped / failed 时 `failure_code` / `failure_message` 必填。 为了让 Heicode 这边在没有真实部署的情况下也能联调 callback 接收逻辑: ``` -POST /api/agnet/_mock/emit_event +POST /api/agent/_mock/emit_event Authorization: Bearer { - "callback_url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "callback_url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "event_type": "phase.changed", "deployment_id": "dep_mock_001", "data": { "from_phase": null, "to_phase": "requirements" } @@ -542,7 +542,7 @@ Authorization: Bearer ``` agnet-cli mock-emit \ - --target https://staging.heicode.local/api/agnet/callbacks \ + --target https://staging.heicode.local/api/agent/callbacks \ --event sk_tool.called \ --deployment dep_mock_001 \ --signing-secret "$(cat /tmp/test-secret)" @@ -578,7 +578,7 @@ agnet-cli mock-emit \ - Heicode 端校验 `X-Agnet-Timestamp` 落在 `now ± 5 分钟` 内 - 超出 → 返回 `400 SIGNATURE_INVALID`(防止回放) -- Agnet 端**必须**用 NTP 同步时钟,最大允许偏移 ±60 秒 +- Agent Runtime 端**必须**用 NTP 同步时钟,最大允许偏移 ±60 秒 --- @@ -616,7 +616,7 @@ agnet-cli mock-emit \ - [ ] 实现 §6 mock-emit 接口 **Heicode Manager 侧**(不依赖 Agent Manager 完成): -- [ ] 实现 `/api/agnet/callbacks/swarm-events` 接收端 +- [ ] 实现 `/api/agent/callbacks/runtime-events` 接收端 - [ ] 实现 §4.3 HMAC 校验、§4.4 幂等去重(复用 Redis SETNX,参考 V2 device-signature nonce 实现) - [ ] 事件入审计表(复用 `agnet_audit_events`) - [ ] 给桌面客户端 push 接口(已有 SSE 通道复用) diff --git a/docs/HEICODE_API_INTEGRATION.md b/docs/HEICODE_API_INTEGRATION.md index 3cde96b..b0702b3 100644 --- a/docs/HEICODE_API_INTEGRATION.md +++ b/docs/HEICODE_API_INTEGRATION.md @@ -23,7 +23,7 @@ - **当前 AKS 镜像 digest**: `sha256:b1931c1172fc23da8234e96dbdca34c4704644c2b2099391b362a48c47dc68f4` - **Base URL(当前联调)**: `http://20.212.121.126` - **Base URL(域名待切换)**: `https://agent-manager.taijiagnet.com` -- **主 API 前缀**: `/api/agnet` +- **主 API 前缀**: `/api/agent` - **Runtime 兼容前缀**: `/api/swarms` ### 1.2 核心功能 @@ -50,7 +50,7 @@ ▼ ┌─────────────────────────────┐ │ Agent Manager API │ -│ /api/agnet/* │ +│ /api/agent/* │ └──────┬──────────────────────┘ │ ▼ @@ -69,7 +69,7 @@ | 系统 | 职责 | 说明 | |------|------|------| | Heicode Manager | 用户、资源绑定、模型网关配置、审批、部署草稿、权限清单、回调持久化、artifact/timeline 展示 | 已有本地控制面和生产页面 | -| Agent Manager / Agnet Runtime | 接收 Manager 传入的部署计划,真实创建/调度子 Agent,执行任务,按回调协议回写状态、产物、用量和审批请求 | 需要支持本文定义的请求与回调字段 | +| Agent Manager / Agent Runtime | 接收 Manager 传入的部署计划,真实创建/调度子 Agent,执行任务,按回调协议回写状态、产物、用量和审批请求 | 需要支持本文定义的请求与回调字段 | | Azure Key Vault | 长期密钥托管 | Manager/Runtime 只能使用 `azkv://...` 引用,不能传明文密钥 | | NewAPI / CodeGW | 模型网关与计费入口 | Runtime 使用 Manager 提供的模型、预算和 `secret_ref` 上下文 | @@ -89,7 +89,7 @@ | Callback HMAC 验签 | 已支持 | 支持 `X-Agnet-Signature` / `X-Agnet-Timestamp` / `X-Agnet-Event-Id` | | Callback 旧认证兼容 | 已支持 | 过渡期仍接受 `X-Agnet-Service-Token` 或 `Authorization: Bearer` | | Callback 幂等 | 已支持 | 优先读 `X-Agnet-Event-Id`,兼容 body `event_id` | -| Runtime 主动回调 | 已支持 | `/api/agnet/deployments` 与 `/api/swarms` 创建的 Runtime 执行阶段会主动推送 status/phase/timeline/agent/tool/artifact 事件 | +| Runtime 主动回调 | 已支持 | `/api/agent/sub-agile/deployments` 与 `/api/swarms` 创建的 Runtime 执行阶段会主动推送 status/phase/timeline/agent/tool/artifact 事件 | | 普通 sub 真实 artifact 回调 | 已支持 | 普通 sub agent 真正执行后会生成 `artifact.created`,不再只返回 completed | | Runtime artifact 内容读取 | 已支持 | Runtime 会优先用 K8s Secret 中的 Azure Blob 凭据上传完整产物;失败时回落本地 artifact store,metadata 中返回 URI、`content_hash` 和下载路径 | | 普通 sub task 终态回调 | 已支持 | 新增 `task.completed` / `task.failed` / `task.blocked` 事件 | @@ -103,7 +103,7 @@ | 顶层 `resource_grants` | 已支持 | 兼容 `agents[].resource_grants` 汇总 | | legacy ResourceGrant 字段 | 已支持 | 兼容 `type / permissions / ref` 与 `resource_type / permission_scope / secret_ref` | | artifact/timeline/SK snapshot 查询 | 已支持 | 从 callback 事件投影到用户态查询接口 | -| `approval.requested` / decision | 已支持 | callback 会持久化审批请求;Runtime 接收 `/api/swarms/{swarm_id}/approvals/{approval_id}` 与 `/api/agnet/deployments/{deployment_id}/approvals/{approval_id}` decision | +| `approval.requested` / decision | 已支持 | callback 会持久化审批请求;Runtime 接收 `/api/swarms/{swarm_id}/approvals/{approval_id}` 与 `/api/agent/sub-agile/deployments/{deployment_id}/approvals/{approval_id}` decision | | `/api/swarms` 运行期查询 | 已支持 | 兼容 `status`、`stop`、`logs`、`events`、`metrics` 查询/控制路径 | | `/api/swarms` 创建校验 | 已支持 | 缺少 `orchestration_plan` / `callback.url` / `sub_mode` / `user_context.user_id` 返回 422;`dry_run:true` 返回 422 且不创建真实 run | | `/api/swarms` 幂等 | 已支持 | 同一个 `X-Idempotency-Key` 返回已有 run,不重复创建 | @@ -124,14 +124,14 @@ | 场景 | 推荐接口 | 当前状态 | |------|----------|----------| -| 健康检查 | `GET /api/agnet/health` | 已支持,无需业务 Header | +| 健康检查 | `GET /api/agent/health` | 已支持,无需业务 Header | | 普通 sub 创建 Runtime run | `POST /api/swarms` | 已支持,要求结构化 `orchestration_plan` 和 `callback.url` | -| 旧版 Agent 部署创建 | `POST /api/agnet/deployments` | 已支持,可兼容结构化 sub plan | -| Runtime 主动事件回写 | `POST /api/agnet/callbacks/swarm-events` | 已支持 HMAC / 旧 token 过渡认证和幂等 | +| 旧版 Agent 部署创建 | `POST /api/agent/sub-agile/deployments` | 已支持,可兼容结构化 sub plan | +| Runtime 主动事件回写 | `POST /api/agent/callbacks/runtime-events` | 已支持 HMAC / 旧 token 过渡认证和幂等 | | 查询 Runtime 状态 | `GET /api/swarms/{swarm_id}` 或 `/status` | 已支持,`deployment_id` 与 `swarm_id` 当前同值 | -| 查询产物 | `GET /api/agnet/user/deployments/{deployment_id}/artifacts` | 已支持,由 callback event 投影 | -| 查询时间线 | `GET /api/agnet/user/deployments/{deployment_id}/timeline` | 已支持,由 callback event 合并 | -| 查询 SK snapshot | `GET /api/agnet/user/deployments/{deployment_id}/sk-snapshots` | 已支持投影查询,独立解析接口待增强 | +| 查询产物 | `GET /api/agent/user/deployments/{deployment_id}/artifacts` | 已支持,由 callback event 投影 | +| 查询时间线 | `GET /api/agent/user/deployments/{deployment_id}/timeline` | 已支持,由 callback event 合并 | +| 查询 SK snapshot | `GET /api/agent/user/deployments/{deployment_id}/sk-snapshots` | 已支持投影查询,独立解析接口待增强 | | 审批 decision | `POST /api/swarms/{swarm_id}/approvals/{approval_id}` | 已支持 `approved` / `rejected` | 当前实现边界: @@ -149,8 +149,8 @@ 1. 创建 Runtime run 后保存返回的 `deployment_id` / `swarm_id`。当前实现里二者同值。 2. 通过 callback 里的 `artifact.created` 事件,或轮询 `GET /api/swarms/{swarm_id}/status` 判断是否已有 artifact。 -3. 调用 `GET /api/agnet/user/deployments/{deployment_id}/artifacts` 获取产物列表。 -4. 从列表中取 `artifact_id`,调用 `GET /api/agnet/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` 下载完整内容。 +3. 调用 `GET /api/agent/user/deployments/{deployment_id}/artifacts` 获取产物列表。 +4. 从列表中取 `artifact_id`,调用 `GET /api/agent/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` 下载完整内容。 5. 如果 Manager 需要直接访问 Runtime 兼容层,也可以调用 `GET /api/swarms/{swarm_id}/artifacts/{artifact_id}/content`。 示例: @@ -162,7 +162,7 @@ DEPLOYMENT_ID="swm_xxx" curl -sS \ -H "Authorization: Bearer ${TOKEN}" \ - "${BASE_URL}/api/agnet/user/deployments/${DEPLOYMENT_ID}/artifacts" + "${BASE_URL}/api/agent/user/deployments/${DEPLOYMENT_ID}/artifacts" ``` 列表响应中的关键字段: @@ -198,7 +198,7 @@ ARTIFACT_ID="art_backend_patch_001" curl -L \ -H "Authorization: Bearer ${TOKEN}" \ -o "${ARTIFACT_ID}.txt" \ - "${BASE_URL}/api/agnet/user/deployments/${DEPLOYMENT_ID}/artifacts/${ARTIFACT_ID}/content" + "${BASE_URL}/api/agent/user/deployments/${DEPLOYMENT_ID}/artifacts/${ARTIFACT_ID}/content" ``` 生产环境产物存储规则: @@ -256,7 +256,7 @@ Authorization: Bearer | `X-Idempotency-Key` | ⚪ | 幂等性键(推荐) | `idem_abc123` | | `Content-Type` | ✅ | 内容类型 | `application/json` | -> `GET /api/agnet/health` 用于 K8s / LB 探活,不要求 `Authorization` 或业务追踪 Header。 +> `GET /api/agent/health` 用于 K8s / LB 探活,不要求 `Authorization` 或业务追踪 Header。 ### 2.3 获取 Service Token @@ -268,13 +268,13 @@ Authorization: Bearer ### 3.1 健康检查 -#### `GET /api/agnet/health` +#### `GET /api/agent/health` 检查服务状态。 **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/health" +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/health" ``` **响应示例**: @@ -294,7 +294,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/health" ### 3.2 创建部署 -#### `POST /api/agnet/deployments` +#### `POST /api/agent/sub-agile/deployments` 创建一个新的 Agent 部署。 @@ -332,7 +332,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/health" } ], "callback": { - "url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key", "subscribed_events": [ "phase.changed", @@ -389,13 +389,13 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/health" - `orchestration_plan.billing_context.default_model_id` / `allowed_model_ids` / `secret_ref` 会透传到 Runtime 配置。 - `resource_grants` 可放在顶层,也可放在 `agents[].resource_grants`,Runtime 会做兼容汇总。 - 如果请求包含 `callback`,Runtime 会按订阅事件主动回调 `deployment.status_changed`、`phase.changed`、`timeline.updated`、`agent.started`、`artifact.created`,并在需要审批时回调 `approval.requested`。 -- `callback.url` 在 `/api/agnet/deployments` 中必须为 `https://`,`callback.signing_secret_ref` 必须为 `azkv://`。 +- `callback.url` 在 `/api/agent/sub-agile/deployments` 中必须为 `https://`,`callback.signing_secret_ref` 必须为 `azkv://`。 --- ### 3.3 列出部署 -#### `GET /api/agnet/deployments` +#### `GET /api/agent/sub-agile/deployments` 获取部署列表,支持过滤和分页。 @@ -410,7 +410,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/health" **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments?user_id=user_123&status=running&limit=10" \ +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments?user_id=user_123&status=running&limit=10" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -445,7 +445,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments?user_id= ### 3.4 获取部署详情 -#### `GET /api/agnet/deployments/{deployment_id}` +#### `GET /api/agent/sub-agile/deployments/{deployment_id}` 获取指定部署的详细信息。 @@ -454,7 +454,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments?user_id= **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2c3d4e5f6" \ +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments/dep_a1b2c3d4e5f6" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -510,7 +510,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 ### 3.5 停止部署 -#### `POST /api/agnet/deployments/{deployment_id}/stop` +#### `POST /api/agent/sub-agile/deployments/{deployment_id}/stop` 停止一个正在运行的部署。 @@ -527,7 +527,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 **请求示例**: ```bash -curl -X POST "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2c3d4e5f6/stop" \ +curl -X POST "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments/dep_a1b2c3d4e5f6/stop" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -551,7 +551,7 @@ curl -X POST "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b ### 3.6 获取部署日志 -#### `GET /api/agnet/deployments/{deployment_id}/logs` +#### `GET /api/agent/sub-agile/deployments/{deployment_id}/logs` 获取部署的实时日志。 @@ -567,7 +567,7 @@ curl -X POST "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2c3d4e5f6/logs?limit=50" \ +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments/dep_a1b2c3d4e5f6/logs?limit=50" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -604,7 +604,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 ### 3.7 获取部署事件 -#### `GET /api/agnet/deployments/{deployment_id}/events` +#### `GET /api/agent/sub-agile/deployments/{deployment_id}/events` 获取部署的事件历史。 @@ -629,7 +629,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2c3d4e5f6/events" \ +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments/dep_a1b2c3d4e5f6/events" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -670,7 +670,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 ### 3.8 获取资源指标 -#### `GET /api/agnet/deployments/{deployment_id}/metrics` +#### `GET /api/agent/sub-agile/deployments/{deployment_id}/metrics` 获取部署的资源使用指标。 @@ -679,7 +679,7 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 **请求示例**: ```bash -curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2c3d4e5f6/metrics" \ +curl -X GET "https://agent-manager.taijiagnet.com/api/agent/sub-agile/deployments/dep_a1b2c3d4e5f6/metrics" \ -H "Authorization: Bearer sk_xxx" \ -H "X-User-ID: user_123" \ -H "X-Binding-Scope: workspace_abc" \ @@ -730,11 +730,11 @@ curl -X GET "https://agent-manager.taijiagnet.com/api/agnet/deployments/dep_a1b2 ### 3.9 Runtime Callback 回写 -#### `POST /api/agnet/callbacks/swarm-events` +#### `POST /api/agent/callbacks/runtime-events` Agent Manager / Runtime 使用该接口向 Heicode Manager 回写 sub 模式事件、阶段变化、产物、预算告警、审批请求和 SK 工具调用结果。该接口是反向通知协议,不能仅依赖 `/events` 轮询替代。 -#### `GET /api/agnet/callbacks/swarm-events/schema` +#### `GET /api/agent/callbacks/runtime-events/schema` 联调前可读取 callback schema。该接口只返回事件类型、分类、必填字段、阶段枚举和 artifact 类型,不返回 token、secret 或任何明文密钥。 @@ -826,7 +826,7 @@ Runtime 发送端签名密钥解析顺序: | 触发时机 | 事件 | |----------|------| -| `/api/agnet/deployments` 创建 accepted/running | `deployment.status_changed`、`phase.changed`、`timeline.updated`、`agent.started`、`artifact.created` | +| `/api/agent/sub-agile/deployments` 创建 accepted/running | `deployment.status_changed`、`phase.changed`、`timeline.updated`、`agent.started`、`artifact.created` | | Swarm 初始化 / 运行 / 完成 / 失败 / 停止 | `deployment.status_changed` | | 规划、实现、检查、完成等阶段变化 | `phase.changed`、`timeline.updated` | | Agent 可运行 | `agent.started` | @@ -879,22 +879,22 @@ Runtime 发送端签名密钥解析顺序: | 方法 | 路径 | 调用方 | 用途 | |------|------|--------|------| -| `POST` | `/api/agnet/user/tasks/{task_id}/deployment-draft` | Heicode 客户端 / Manager 前端 | 从任务卡生成 Agnet deployment draft | -| `POST` | `/api/agnet/user/deployments` | Heicode 客户端 / Manager 前端 | 用户态创建部署记录 | -| `GET` | `/api/agnet/user/deployments` | Heicode 客户端 / Manager 前端 | 用户态部署列表 | -| `GET` | `/api/agnet/user/deployments/{deployment_id}` | Heicode 客户端 / Manager 前端 | 用户态部署详情 | +| `POST` | `/api/agent/user/tasks/{task_id}/deployment-draft` | Heicode 客户端 / Manager 前端 | 从任务卡生成 Agent deployment draft | +| `POST` | `/api/agent/user/deployments` | Heicode 客户端 / Manager 前端 | 用户态创建部署记录 | +| `GET` | `/api/agent/user/deployments` | Heicode 客户端 / Manager 前端 | 用户态部署列表 | +| `GET` | `/api/agent/user/deployments/{deployment_id}` | Heicode 客户端 / Manager 前端 | 用户态部署详情 | | `POST` | `/api/swarms` | Runtime 对接适配 / Manager | 创建 Swarm Run 的兼容入口,目前映射到 Manager 本地部署控制面 | -| `POST` | `/api/agnet/callbacks/swarm-events` | Agent Manager / Runtime | Runtime 回写状态、事件、artifact | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/artifacts` | Heicode 客户端 / Manager 前端 | 查询部署产物 | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` | Heicode 客户端 / Manager 前端 | 下载完整产物内容 | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/sk-snapshots` | Heicode 客户端 / Manager 前端 | 查询 SK 快照 | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/timeline` | Heicode 客户端 / Manager 前端 | 查询合并时间线 | +| `POST` | `/api/agent/callbacks/runtime-events` | Agent Manager / Runtime | Runtime 回写状态、事件、artifact | +| `GET` | `/api/agent/user/deployments/{deployment_id}/artifacts` | Heicode 客户端 / Manager 前端 | 查询部署产物 | +| `GET` | `/api/agent/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` | Heicode 客户端 / Manager 前端 | 下载完整产物内容 | +| `GET` | `/api/agent/user/deployments/{deployment_id}/sk-snapshots` | Heicode 客户端 / Manager 前端 | 查询 SK 快照 | +| `GET` | `/api/agent/user/deployments/{deployment_id}/timeline` | Heicode 客户端 / Manager 前端 | 查询合并时间线 | 说明: 1. `POST /api/swarms` 当前返回 `deployment_id` 和 `swarm_id`;当前二者同值,均可用于 Runtime 查询和停止。 2. 后续如果 Runtime 返回自己的真实 `swarm_id`,Manager 需要保存 `deployment_id <-> swarm_id` 映射。 -3. Runtime 侧不能只支持 `/api/agnet/deployments`,否则无法覆盖 Heicode 用户态任务流。 +3. Runtime 侧不能只支持 `/api/agent/sub-agile/deployments`,否则无法覆盖 Heicode 用户态任务流。 #### `POST /api/swarms` @@ -951,7 +951,7 @@ Heicode sub 模式兼容入口。该接口接受结构化 `orchestration_plan` "resource_grants": [] }, "callback": { - "url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key" } } @@ -980,7 +980,7 @@ Heicode sub 模式兼容入口。该接口接受结构化 `orchestration_plan` } }, "callback": { - "url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key" } } @@ -1039,7 +1039,7 @@ Heicode sub 模式兼容入口。该接口接受结构化 `orchestration_plan` 如果普通 sub 不走 `/api/swarms`,也支持: ```http -POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id} +POST /api/agent/sub-agile/deployments/{deployment_id}/approvals/{approval_id} ``` **响应示例**: @@ -1087,7 +1087,7 @@ POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id} } ``` -#### `GET /api/agnet/user/deployments/{deployment_id}/artifacts` +#### `GET /api/agent/user/deployments/{deployment_id}/artifacts` 查询 Runtime 通过 `artifact.created` callback 回写的产物。当前 Manager 从 callback event payload 投影生成响应;大文件只返回 `uri`、摘要、大小和 hash 信息,完整内容需要继续调用 artifact content 接口读取。完整操作流程见 [1.7 产物获取速查](#17-产物获取速查)。 @@ -1119,7 +1119,7 @@ POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id} } ``` -#### `GET /api/agnet/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` +#### `GET /api/agent/user/deployments/{deployment_id}/artifacts/{artifact_id}/content` 读取 Runtime artifact 的完整内容。该接口是 Manager / 前端获取产物正文的推荐入口,要求携带 `Authorization: Bearer `。 @@ -1138,7 +1138,7 @@ Azure Blob 凭据来自 `RUNTIME_ARTIFACT_BLOB_SECRET_NAMESPACE` / `RUNTIME_ARTI curl -L \ -H "Authorization: Bearer " \ -o artifact-output.txt \ - "https://agent-manager.taijiagnet.com/api/agnet/user/deployments/{deployment_id}/artifacts/{artifact_id}/content" + "https://agent-manager.taijiagnet.com/api/agent/user/deployments/{deployment_id}/artifacts/{artifact_id}/content" ``` 如果调用方已经持有 Runtime `swarm_id`,也可以直接使用兼容接口: @@ -1150,7 +1150,7 @@ curl -L \ "https://agent-manager.taijiagnet.com/api/swarms/{swarm_id}/artifacts/{artifact_id}/content" ``` -#### `GET /api/agnet/user/deployments/{deployment_id}/timeline` +#### `GET /api/agent/user/deployments/{deployment_id}/timeline` 查询合并时间线。当前 Manager 会合并 `timeline.updated`、阶段变化、Agent 状态、预算告警、审批请求、artifact 与 SK 工具事件。 @@ -1180,7 +1180,7 @@ curl -L \ } ``` -#### `GET /api/agnet/user/deployments/{deployment_id}/sk-snapshots` +#### `GET /api/agent/user/deployments/{deployment_id}/sk-snapshots` 查询 Runtime 回写的 SK snapshot。当前 Manager 从 `sk_tool.called/completed/failed` 和包含 `sk_snapshot` 的 artifact 事件投影生成响应。 @@ -1322,7 +1322,7 @@ Heicode sub 模式使用扩展 Resource Grant 表达任务资源授权。Runtime ### 4.8 Artifact 回写模型 -Runtime 通过 `/api/agnet/callbacks/swarm-events` 回写产物事件,Manager 将其持久化后供用户态接口查询。 +Runtime 通过 `/api/agent/callbacks/runtime-events` 回写产物事件,Manager 将其持久化后供用户态接口查询。 ```json { @@ -1458,7 +1458,7 @@ create_payload = { } response = requests.post( - f"{BASE_URL}/api/agnet/deployments", + f"{BASE_URL}/api/agent/sub-agile/deployments", headers=headers, json=create_payload ) @@ -1471,7 +1471,7 @@ time.sleep(120) # 等待 2 分钟 # 3. 获取部署详情 response = requests.get( - f"{BASE_URL}/api/agnet/deployments/{deployment_id}", + f"{BASE_URL}/api/agent/sub-agile/deployments/{deployment_id}", headers=headers ) details = response.json() @@ -1479,7 +1479,7 @@ print(f"📊 部署状态: {details['status']}") # 4. 获取实时日志 response = requests.get( - f"{BASE_URL}/api/agnet/deployments/{deployment_id}/logs?limit=20", + f"{BASE_URL}/api/agent/sub-agile/deployments/{deployment_id}/logs?limit=20", headers=headers ) logs = response.json() @@ -1487,7 +1487,7 @@ print(f"📝 最新日志: {len(logs['logs'])} 条") # 5. 获取资源指标 response = requests.get( - f"{BASE_URL}/api/agnet/deployments/{deployment_id}/metrics", + f"{BASE_URL}/api/agent/sub-agile/deployments/{deployment_id}/metrics", headers=headers ) metrics = response.json() @@ -1499,7 +1499,7 @@ stop_payload = { "reason": "Task completed successfully" } response = requests.post( - f"{BASE_URL}/api/agnet/deployments/{deployment_id}/stop", + f"{BASE_URL}/api/agent/sub-agile/deployments/{deployment_id}/stop", headers=headers, json=stop_payload ) @@ -1527,14 +1527,14 @@ headers = { # 第一次请求 response1 = requests.post( - f"{BASE_URL}/api/agnet/deployments", + f"{BASE_URL}/api/agent/sub-agile/deployments", headers=headers, json=create_payload ) # 重复请求(使用相同的 idempotency_key) response2 = requests.post( - f"{BASE_URL}/api/agnet/deployments", + f"{BASE_URL}/api/agent/sub-agile/deployments", headers=headers, json=create_payload ) @@ -1589,7 +1589,7 @@ payload = { ] }, "callback": { - "url": "https://code.xinghanlab.com/api/agnet/callbacks/swarm-events", + "url": "https://code.xinghanlab.com/api/agent/callbacks/runtime-events", "signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agnet-callback-signing-key" } } @@ -1604,7 +1604,7 @@ status.raise_for_status() print(status.json()["status"]) timeline = requests.get( - f"{BASE_URL}/api/agnet/user/deployments/{run['deployment_id']}/timeline", + f"{BASE_URL}/api/agent/user/deployments/{run['deployment_id']}/timeline", headers={"Authorization": f"Bearer {TOKEN}"} ) timeline.raise_for_status() @@ -1655,7 +1655,7 @@ print(len(timeline.json()["timeline"])) ```python try: response = requests.post( - f"{BASE_URL}/api/agnet/deployments", + f"{BASE_URL}/api/agent/sub-agile/deployments", headers=headers, json=create_payload ) @@ -1763,7 +1763,7 @@ except requests.exceptions.HTTPError as e: | v2.1.6 | 2026-05-29 | 修复普通 sub 真实执行后缺失 `artifact.created` 的问题,新增 `task.completed` / `task.failed` / `task.blocked` 事件,修复 deployment 与 agents 终态不一致,`/api/swarms/{id}/logs` 改为返回 Runtime 聚合摘要;部署镜像更新为 `heicode-v2-20260529120632` | | v2.1.5 | 2026-05-28 | 文档修订:新增 v2.1.4 联调速查,补充 `/api/swarms` 最小请求、校验失败、状态响应和普通 sub 联调示例;修正 callback 当前实现为失败只记录 warning,重试/死信/replay 为后续增强 | | v2.1.4 | 2026-05-28 | 按普通 sub 联调整改要求补齐 `/api/swarms` 参数校验、`dry_run` 拒绝、`deployment_id` 返回、detail 根路径、幂等创建和 usage/cost callback 字段;当前联调 Base URL 明确为 `http://20.212.121.126`,部署镜像更新为 `heicode-v2-20260528164612` | -| v2.1.3 | 2026-05-28 | 按普通 sub 敏捷模式任务清单补齐 `/api/agnet/deployments` 主动回调、`role_template` 兼容、callback schema、`/api/swarms/{id}` stop/status/logs/events/metrics、approval decision 接收路径,部署镜像更新为 `heicode-v2-20260528161931` | +| v2.1.3 | 2026-05-28 | 按普通 sub 敏捷模式任务清单补齐 `/api/agent/sub-agile/deployments` 主动回调、`role_template` 兼容、callback schema、`/api/swarms/{id}` stop/status/logs/events/metrics、approval decision 接收路径,部署镜像更新为 `heicode-v2-20260528161931` | | v2.1.2 | 2026-05-28 | Agent Manager Runtime 支持按 callback 配置主动推送 status/phase/timeline/agent/tool/artifact 事件,补充发送端签名密钥解析顺序和失败策略,部署镜像更新为 `heicode-v2-20260528144233` | | v2.1.1 | 2026-05-27 | 同步 Manager 当前实现状态:callback HMAC/旧 token 兼容、payload 投影、默认 subscribed_events、artifact/timeline/SK snapshot 查询示例、部署镜像版本 | | v2.1.0 | 2026-05-26 | 补充 Heicode sub 模式敏捷开发契约、`/api/swarms` 兼容入口、`azkv://` secret_ref、artifact/timeline/SK snapshot 模型 | diff --git a/docs/HEICODE_IMPLEMENTATION_STATUS.md b/docs/HEICODE_IMPLEMENTATION_STATUS.md index 6e33b2e..6380b19 100644 --- a/docs/HEICODE_IMPLEMENTATION_STATUS.md +++ b/docs/HEICODE_IMPLEMENTATION_STATUS.md @@ -33,10 +33,10 @@ | deployment/agent 状态一致性 | ✅ 完成 | deployment 完成或失败时,agents 会同步进入终态 | | `/api/swarms/{id}/logs` 兜底日志 | ✅ 完成 | 返回 Runtime 聚合日志摘要,而不是固定占位文本 | | Callback HMAC/幂等接收 | ✅ 完成 | 支持 v2.1 HMAC,兼容旧 service token | -| artifact 查询 | ✅ 完成 | `GET /api/agnet/user/deployments/{deployment_id}/artifacts` | -| timeline 查询 | ✅ 完成 | `GET /api/agnet/user/deployments/{deployment_id}/timeline` | -| SK snapshot 查询投影 | ✅ 完成 | `GET /api/agnet/user/deployments/{deployment_id}/sk-snapshots` | -| 审批 decision | ✅ 完成 | 支持 `/api/swarms/.../approvals/...` 与 `/api/agnet/deployments/.../approvals/...` | +| artifact 查询 | ✅ 完成 | `GET /api/agent/user/deployments/{deployment_id}/artifacts` | +| timeline 查询 | ✅ 完成 | `GET /api/agent/user/deployments/{deployment_id}/timeline` | +| SK snapshot 查询投影 | ✅ 完成 | `GET /api/agent/user/deployments/{deployment_id}/sk-snapshots` | +| 审批 decision | ✅ 完成 | 支持 `/api/swarms/.../approvals/...` 与 `/api/agent/sub-agile/deployments/.../approvals/...` | --- @@ -48,17 +48,17 @@ | 接口 | 路径 | 状态 | 文件位置 | |------|------|------|----------| -| 1️⃣ 健康检查 | `GET /api/agnet/health` | ✅ 完成 | `api/agnet/router.py:20` | -| 2️⃣ 创建部署 | `POST /api/agnet/deployments` | ✅ 完成 | `api/agnet/deployments.py:123` | -| 3️⃣ 列出部署 | `GET /api/agnet/deployments` | ✅ 完成 | `api/agnet/deployments.py:346` | -| 4️⃣ 获取部署详情 | `GET /api/agnet/deployments/{id}` | ✅ 完成 | `api/agnet/deployments.py:408` | -| 5️⃣ 停止部署 | `POST /api/agnet/deployments/{id}/stop` | ✅ 完成 | `api/agnet/deployments.py:469` | -| 6️⃣ 获取日志 | `GET /api/agnet/deployments/{id}/logs` | ✅ 完成 | `api/agnet/deployments.py:596` | -| 7️⃣ 获取事件 | `GET /api/agnet/deployments/{id}/events` | ✅ 完成 | `api/agnet/deployments.py:679` | -| 8️⃣ 获取指标 | `GET /api/agnet/deployments/{id}/metrics` | ✅ 完成 | `api/agnet/deployments.py:731` | +| 1️⃣ 健康检查 | `GET /api/agent/health` | ✅ 完成 | `api/agnet/router.py:20` | +| 2️⃣ 创建部署 | `POST /api/agent/sub-agile/deployments` | ✅ 完成 | `api/agnet/deployments.py:123` | +| 3️⃣ 列出部署 | `GET /api/agent/sub-agile/deployments` | ✅ 完成 | `api/agnet/deployments.py:346` | +| 4️⃣ 获取部署详情 | `GET /api/agent/sub-agile/deployments/{id}` | ✅ 完成 | `api/agnet/deployments.py:408` | +| 5️⃣ 停止部署 | `POST /api/agent/sub-agile/deployments/{id}/stop` | ✅ 完成 | `api/agnet/deployments.py:469` | +| 6️⃣ 获取日志 | `GET /api/agent/sub-agile/deployments/{id}/logs` | ✅ 完成 | `api/agnet/deployments.py:596` | +| 7️⃣ 获取事件 | `GET /api/agent/sub-agile/deployments/{id}/events` | ✅ 完成 | `api/agnet/deployments.py:679` | +| 8️⃣ 获取指标 | `GET /api/agent/sub-agile/deployments/{id}/metrics` | ✅ 完成 | `api/agnet/deployments.py:731` | | 9️⃣ Runtime 兼容入口 | `POST /api/swarms` | ✅ 完成 | `api/swarm/router.py` | -| 🔟 Callback 接收 | `POST /api/agnet/callbacks/swarm-events` | ✅ 完成 | `api/agnet/callbacks.py` | -| 1️⃣1️⃣ 用户态观测 | `/api/agnet/user/deployments/{id}/{artifacts,timeline,sk-snapshots}` | ✅ 完成 | `api/agnet/callbacks.py` | +| 🔟 Callback 接收 | `POST /api/agent/callbacks/runtime-events` | ✅ 完成 | `api/agnet/callbacks.py` | +| 1️⃣1️⃣ 用户态观测 | `/api/agent/user/deployments/{id}/{artifacts,timeline,sk-snapshots}` | ✅ 完成 | `api/agnet/callbacks.py` | **实现亮点**: - ✅ 完整的请求/响应模型定义 @@ -220,7 +220,7 @@ def create_service_account(self, namespace: str, role: str, user_id: str): ### 1. SSE 实时日志流 -**接口**: `GET /api/agnet/deployments/{id}/logs/stream` +**接口**: `GET /api/agent/sub-agile/deployments/{id}/logs/stream` **状态**: ❌ 未实现 @@ -247,7 +247,7 @@ async def stream_logs(deployment_id: str): ### 2. 资源作用域监控快照 -**接口**: `GET /api/agnet/projects/{binding_scope}/dashboard-snapshot` +**接口**: `GET /api/agent/projects/{binding_scope}/dashboard-snapshot` **状态**: ⚠️ 后续增强 @@ -263,7 +263,7 @@ async def stream_logs(deployment_id: str): ### 3. SK 快照解析 -**接口**: `POST /api/agnet/sk-snapshots/resolve` +**接口**: `POST /api/agent/sk-snapshots/resolve` **状态**: ⚠️ 后续增强 @@ -273,7 +273,7 @@ async def stream_logs(deployment_id: str): ### 4. SK 快照查询 -**接口**: `GET /api/agnet/user/deployments/{id}/sk-snapshots` +**接口**: `GET /api/agent/user/deployments/{id}/sk-snapshots` **状态**: ✅ 已实现(v2.1.4) @@ -402,11 +402,11 @@ async def get_deployment_logs(...): **优先级: 中** 1. ⚪ 实现资源作用域监控快照 - - `GET /api/agnet/projects/{binding_scope}/dashboard-snapshot` + - `GET /api/agent/projects/{binding_scope}/dashboard-snapshot` 2. ⚪ 实现 SK 快照功能 - - `POST /api/agnet/sk-snapshots/resolve` - - `GET /api/agnet/deployments/{id}/sk-snapshots` + - `POST /api/agent/sk-snapshots/resolve` + - `GET /api/agent/sub-agile/deployments/{id}/sk-snapshots` ### Phase 3: 基础设施配置(3-5 天) @@ -425,7 +425,7 @@ async def get_deployment_logs(...): **优先级: 低** 1. ⚪ 实现 SSE 实时日志流 - - `GET /api/agnet/deployments/{id}/logs/stream` + - `GET /api/agent/sub-agile/deployments/{id}/logs/stream` --- @@ -458,7 +458,7 @@ async def get_deployment_logs(...): ### AKS 部署版本 **当前 AKS 上的版本是 `heicode-v2-20260529120632`**,包含: -- ✅ 完整的 Heicode Agent API (`/api/agnet/*`) +- ✅ 完整的 Heicode Agent API (`/api/agent/*`) - ✅ `/api/swarms` Runtime 兼容入口 - ✅ Runtime 主动 callback、artifact、timeline、SK snapshot 查询 - ✅ 普通 sub 真实执行后的 `artifact.created` 与 `task.*` 终态回调 diff --git a/docs/HEICODE_SUB_MODE_RUNTIME_INTEGRATION.md b/docs/HEICODE_SUB_MODE_RUNTIME_INTEGRATION.md index 7aae9c1..c56e7d8 100644 --- a/docs/HEICODE_SUB_MODE_RUNTIME_INTEGRATION.md +++ b/docs/HEICODE_SUB_MODE_RUNTIME_INTEGRATION.md @@ -1,142 +1,120 @@ -# Heicode Sub Mode Runtime 对接指南 +# Heicode Sub Mode Runtime 接入说明 更新时间:2026-06-01 -本文档是给 **Manager / 客户端 / 平台接入方** 的 sub mode 对接指南。目标不是解释历史背景,而是让别人能够基于本文档直接接通当前仓库提供的 **Sub Agile / 普通 sub 模式 Runtime**。 +本文档描述当前仓库作为 **Sub Agile / 普通 sub 模式 Runtime** 时,对 Manager 暴露的接入契约。 -## 1. 先记结论 +这不是客户端主调用协议。 +生产客户端主调用协议应由 `heicode-manager` 的 `/api/heicode/*` 定义并统一归口。 + +## 1. 文档边界 当前仓库只负责: - `sub_agile` / 普通 sub 模式 Runtime +- Manager 下发后已校验的执行计划 +- Runtime 事实回传:状态、事件、产物、审批请求、诊断信息 当前仓库不负责: - 真正的 Swarm 产品模式 -- 独立的 swarm-only API +- 客户端主调用协议 +- 客户端展示状态裁决 +- 本地修改的最终可信版本管理 +- 云部署目标选择与云密钥直连 命名约定: - `agent`:主命名,新的标准入口 -- `agnet`:兼容命名,旧调用方继续可用 -- `/api/swarms`:仅是 sub-mode compatibility API,不代表当前仓库实现独立 swarm 产品 +- `agnet`:兼容命名,历史调用方继续可用 +- `/api/swarms`:sub-mode compatibility API,不表示当前仓库实现独立 Swarm 系统 -推荐接入原则: - -1. 新接入统一走 `/api/agent/*` -2. 旧系统暂时可继续走 `/api/agnet/*` -3. 只有历史 Runtime 兼容方才使用 `/api/swarms` - -## 2. 推荐接法 - -### 2.1 健康检查 - -主路径: +生产调用边界: ```text -GET /api/agent/health +客户端 -> Manager /api/heicode/sub-agile/* +Manager -> agent_management /api/agent/sub-agile/* +agent_management -> Manager /api/agent/callbacks/runtime-events +客户端 <- Manager display_status / workflow / artifacts / diagnostics ``` -兼容路径: +结论: + +- 生产客户端不应直连本 Runtime +- 本文档面向 Runtime 接入方、Manager 调用方、联调工程师 + +## 2. 主路径与兼容路径 + +### 2.1 主路径 ```text -GET /api/agnet/health -``` +GET /api/agent/health -返回示例: - -```json -{ - "success": true, - "data": { - "status": "healthy", - "service": "agent-manager-sub-mode-runtime", - "version": "1.0.0", - "phase": "sub-mode-runtime" - } -} -``` - -### 2.2 创建 deployment - -主路径: - -```text POST /api/agent/sub-agile/deployments +GET /api/agent/sub-agile/deployments +GET /api/agent/sub-agile/deployments/{deployment_id} +POST /api/agent/sub-agile/deployments/{deployment_id}/stop +POST /api/agent/sub-agile/deployments/{deployment_id}/approvals/{approval_id} +GET /api/agent/sub-agile/deployments/{deployment_id}/logs +GET /api/agent/sub-agile/deployments/{deployment_id}/events +GET /api/agent/sub-agile/deployments/{deployment_id}/metrics + +POST /api/agent/callbacks/runtime-events +GET /api/agent/callbacks/runtime-events/schema ``` -兼容路径: +### 2.2 兼容路径 ```text +GET /api/agnet/health POST /api/agnet/deployments +GET /api/agnet/deployments +GET /api/agnet/deployments/{deployment_id} +POST /api/agnet/deployments/{deployment_id}/stop +POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id} +GET /api/agnet/deployments/{deployment_id}/logs +GET /api/agnet/deployments/{deployment_id}/events +GET /api/agnet/deployments/{deployment_id}/metrics +POST /api/agnet/callbacks/swarm-events +GET /api/agnet/callbacks/swarm-events/schema ``` -Runtime 兼容创建路径: +### 2.3 Legacy compatibility API ```text POST /api/swarms -``` - -如果你是新接入方,优先使用: - -```text -POST /api/agent/sub-agile/deployments -``` - -### 2.3 查询状态 - -主路径: - -```text -GET /api/agent/sub-agile/deployments/{deployment_id} -``` - -兼容路径: - -```text -GET /api/agnet/deployments/{deployment_id} -GET /api/swarms/{swarm_id} -GET /api/swarms/{swarm_id}/status -``` - -### 2.4 停止与审批 - -主路径: - -```text -POST /api/agent/sub-agile/deployments/{deployment_id}/stop -POST /api/agent/sub-agile/deployments/{deployment_id}/approvals/{approval_id} -``` - -兼容路径: - -```text -POST /api/agnet/deployments/{deployment_id}/stop -POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id} +GET /api/swarms/{swarm_id} +GET /api/swarms/{swarm_id}/status POST /api/swarms/{swarm_id}/stop +GET /api/swarms/{swarm_id}/logs +GET /api/swarms/{swarm_id}/events +GET /api/swarms/{swarm_id}/metrics +GET /api/swarms/{swarm_id}/artifacts/{artifact_id}/content POST /api/swarms/{swarm_id}/approvals/{approval_id} ``` -### 2.5 读取产物 +### 2.4 用户态产物 / 时间线查询 -推荐路径: +当前仓库仍保留以下内部 / 兼容查询面: ```text GET /api/agent/user/deployments/{deployment_id}/artifacts GET /api/agent/user/deployments/{deployment_id}/artifacts/{artifact_id}/content +GET /api/agent/user/deployments/{deployment_id}/timeline +GET /api/agent/user/deployments/{deployment_id}/sk-snapshots ``` -兼容路径: +说明: -```text -GET /api/agnet/user/deployments/{deployment_id}/artifacts -GET /api/agnet/user/deployments/{deployment_id}/artifacts/{artifact_id}/content -GET /api/swarms/{swarm_id}/artifacts/{artifact_id}/content -``` +- 这些路径更适合作为 Runtime / Manager 内部或兼容查询面 +- 生产客户端不应直接消费这些路径 +- 生产客户端应通过 Manager 的 `/api/heicode/*` 查询 artifacts / workflow / diagnostics -## 3. 状态语义 +## 3. 状态语义与裁决边界 -当前对外统一投影为以下状态: +### 3.1 Runtime 当前返回状态集合 + +当前 Runtime 对外统一投影: ```text accepted @@ -147,26 +125,51 @@ failed stopped ``` -含义建议: +### 3.2 Runtime 状态不等于客户端展示状态 -- `accepted`:Runtime 已接单,尚未进入明确执行态 -- `running`:至少有一个 subagent 正在执行 -- `waiting_approval`:Runtime 请求用户审批,等待 decision -- `completed`:任务完成,并且已经有终态结果或产物 -- `failed`:执行失败 -- `stopped`:被显式停止 +统一方案中应区分: -注意: +```text +client_task_status +cloud_deployment_status +runtime_execution_status +display_status +``` -- 新创建 deployment 默认返回 `accepted` -- `approval.requested` 会把展示状态投影为 `waiting_approval` -- `/api/swarms` 虽然内部复用旧表和旧 runtime 记录,但对外也返回同一套状态集合 +当前 Runtime 返回的 `status` 更接近: + +```text +runtime_execution_status +``` + +尤其需要注意: + +- Runtime `completed` 不等于用户最终看到的 `completed` +- 最终 `display_status` 必须由 Manager 根据结构化产物事实裁决 + +Manager 可能额外裁决出: + +```text +queued +runtime_syncing +runtime_accepted +waiting_input +completed_without_deliverable +needs_codegen +offline_pending +``` + +推荐裁决原则: + +```text +Runtime completed + has_deliverable=true + summary_only=false -> completed +Runtime completed + summary_only=true -> completed_without_deliverable 或 needs_codegen +Runtime completed + 无真实 artifact -> completed_without_deliverable 或 needs_codegen +``` ## 4. 推荐请求结构 -### 4.1 新接入推荐请求 - -推荐你用结构化 sub mode 请求,而不是只发自然语言字符串。 +建议 Manager 传入结构化 sub mode 计划,而不是裸自然语言。 示例: @@ -204,12 +207,6 @@ stopped "template": "a2a_litellm_agent", "model": "gpt-5.4", "capabilities": ["code", "api", "test"] - }, - { - "role": "frontend", - "template": "a2a_litellm_agent", - "model": "gpt-5.4", - "capabilities": ["ui", "react", "css"] } ] }, @@ -219,99 +216,46 @@ stopped } ``` -### 4.2 最低必填项 - -如果走 `/api/swarms` 兼容入口,最低要求至少要有: +最低必填项: - `orchestration_plan` - `orchestration_plan.sub_mode` - `orchestration_plan.user_context.user_id` - `callback.url` -否则会返回 `422` +## 5. 模型来源与信任边界 -## 5. 创建响应与查询响应 +生产环境中,Runtime 不应信任客户端直传的模型选择。 -### 5.1 创建响应示例 +正确边界: -```json -{ - "deployment_id": "swm_xxx", - "swarm_id": "swm_xxx", - "status": "accepted", - "agents": [ - { - "agent_id": "agi_backend_xxx", - "role": "backend", - "status": "pending", - "namespace": "swarm-swm-xxxx-backend", - "service_url": "http://agent-....svc.cluster.local:8000" - } - ], - "created_at": "2026-06-01T12:00:00Z", - "estimated_ready_at": "2026-06-01T12:02:00Z" -} +```text +客户端选择模型 +Manager 校验模型、套餐、权限、预算、allowed_model_ids +Manager 下发已校验 orchestration_plan +Runtime 只消费 Manager 下发的 model / billing_context / allowed_model_ids ``` -字段说明: +约定: -- `deployment_id`:对外主标识 -- `swarm_id`:仅为兼容字段;当前通常与 `deployment_id` 相同 -- `agents`:当前 runtime 里为本次执行创建的 subagent 实例 - -### 5.2 状态响应示例 - -```json -{ - "deployment_id": "swm_xxx", - "swarm_id": "swm_xxx", - "status": "completed", - "phase": "development", - "progress": 100, - "agents": [ - { - "agent_id": "agi_backend_xxx", - "role": "backend", - "status": "completed", - "output": "后端实现摘要..." - } - ], - "metrics": { - "total_messages": 4, - "tokens_used": 1514, - "elapsed_seconds": 33 - }, - "artifacts": [ - { - "artifact_id": "art_xxx_backend_1", - "artifact_type": "code_patch", - "title": "backend task delivery", - "summary": "后端实现摘要...", - "uri": "azblob://...", - "metadata": { - "runtime_deployment_id": "swm_xxx", - "download_path": "/api/swarms/swm_xxx/artifacts/art_xxx_backend_1/content" - } - } - ] -} -``` +- Runtime 只信任 Manager 已校验的 `orchestration_plan` +- Runtime 不应把客户端未校验的 `model` 视为最终可信配置 ## 6. 回调事件 -### 6.1 主回调入口 +主回调入口: ```text POST /api/agent/callbacks/runtime-events ``` -### 6.2 兼容回调入口 +兼容回调入口: ```text POST /api/agnet/callbacks/swarm-events ``` -### 6.3 当前支持的关键事件 +当前支持的关键事件: - `deployment.status_changed` - `phase.changed` @@ -329,94 +273,161 @@ POST /api/agnet/callbacks/swarm-events - `sk_tool.failed` - `budget.alert` -### 6.4 接入建议 - -对接方至少应该消费: +最小消费建议: 1. `deployment.status_changed` 2. `phase.changed` 3. `artifact.created` 4. `approval.requested` -如果你只做最小接入,这四类事件足够支撑: +## 7. 产物语义 -- 状态展示 -- 阶段进度 -- 产物列表刷新 -- 审批按钮展示 +### 7.1 当前真实 artifact -## 7. 产物读取约定 +当前 Runtime 真实产物通常以: -### 7.1 推荐读取顺序 +- `code_patch` +- `document` -推荐按照这个顺序读取结果: +返回,并提供: -1. 查询 deployment 状态 -2. 等待 `status=completed`,或者在 `artifacts` 不为空时提前读取 -3. 调用 artifacts list 接口获取 `artifact_id` -4. 再通过 content 接口拉完整正文 +- `artifact_id` +- `summary` +- `uri` +- `metadata.download_path` -### 7.2 synthesized fallback artifact +### 7.2 fallback artifact -如果真实 agent 没有产出具体 artifact,runtime 会生成 fallback artifact。 +当真实 agent 没有产出具体 artifact 时,Runtime 会生成 fallback artifact。 -约定: - -- fallback artifact 仍然会出现在 artifacts 列表中 -- 它的用途是让 Manager 和客户端至少有一个可展示终态结果 -- 识别方式是: +从本次升级开始,fallback artifact 必须稳定标记: ```json { "metadata": { - "synthesized": true + "synthesized": true, + "summary_only": true } } ``` -## 8. 真实联调建议 +语义说明: -这是本次线上验证后的建议,不是理论建议。 +- `synthesized=true`:说明该产物是 Runtime 合成的兼容性结果 +- `summary_only=true`:说明该产物只适合展示失败 / 总结,不应直接作为代码类任务的有效交付依据 -### 8.1 当前稳定范围 +Manager 不应将 `summary_only=true` 的 artifact 作为代码任务 `completed` 的充分条件。 -当前 runtime 对以下任务更稳定: +### 7.3 project_folder artifact(推荐扩展) + +对于结构性代码交付,统一方案推荐优先使用: + +```text +artifact_type = project_folder +``` + +推荐形态: + +```json +{ + "artifact_id": "art_project_xxx", + "artifact_type": "project_folder", + "title": "Oracle Cloud Agency Site", + "summary": "包含 frontend、backend、docs 和部署配置的完整项目。", + "metadata": { + "root_dir": "oracle-cloud-agency-site", + "manifest_uri": "runtime://run_xxx/artifacts/art_project_xxx/manifest", + "archive_uri": "runtime://run_xxx/artifacts/art_project_xxx/archive.zip", + "content_hash": "sha256:project-tree-hash", + "file_count": 42, + "directory_count": 8 + } +} +``` + +当前仓库尚未将 `project_folder` 作为默认真实产物类型,但后续扩展建议以此为主,而不是长期停留在单正文 `content` 下载模式。 + +## 8. 本地修改与 artifact revision(推荐扩展) + +统一方案要求: + +- 用户本地修改项目文件夹,不等于云端产物自动更新 +- 客户端必须显式上传 local edit +- Manager 保存 `project artifact revision` +- Runtime 后续执行必须以最新 accepted revision 为基线 + +当前仓库尚未把这套 revision 协议实现为正式 Runtime 接口,但建议保留以下扩展方向: + +```text +POST /api/agent/sub-agile/deployments/{deployment_id}/artifact-edits +``` + +推荐事件形态: + +```json +{ + "event_type": "artifact.local_edit_received", + "task_id": "task_xxx", + "deployment_id": "dep_xxx", + "runtime_deployment_id": "run_xxx", + "artifact_id": "art_project_xxx", + "project_revision": 2, + "source": "client_local_edit", + "manifest_uri": "manager://tasks/task_xxx/artifacts/art_project_xxx/revisions/2/manifest", + "archive_uri": "manager://tasks/task_xxx/artifacts/art_project_xxx/revisions/2/archive", + "content_hash": "sha256:new" +} +``` + +## 9. 云部署生命周期(推荐扩展) + +统一方案中,云部署不应由客户端直传云密钥并直接驱动 Runtime。 + +正确边界: + +```text +客户端只选择 target / environment / resource_binding_id +Manager 负责校验、审批、凭证解析、预算和审计 +Runtime 或 Deploy Worker 执行 provider adapter +部署结果通过 deployment_manifest artifact 和 deployment events 回传 +``` + +当前 Runtime 文档仅做说明,不将云部署声明为本仓库已完整实现能力。 + +## 10. 真实联调建议 + +### 10.1 当前稳定范围 + +当前 Runtime 更稳定的任务类型: - 小型单文件函数生成 - 小型 React 组件生成 - 中小型实现摘要 / 代码骨架任务 +- 经输出收缩后的中型真实编程任务 -### 8.2 当前不稳定范围 +### 10.2 当前高风险任务 -当前 runtime 在以下任务上可能失败: +高风险特征: -- 单次 prompt 很长的真实开发任务 -- 要求一次性输出大段后端 + 前端 + reviewer 的任务 -- 输出内容过大、tokens 较高的代码生成任务 +- 一次性要求完整项目所有文件 +- 单 agent 输出过长代码、长解释、长测试、长部署说明 +- 多角色同时高负载、每个角色都要求大体量正文 -实际线上现象: +真实现象: -- 较大的真实编程任务可能在模型网关返回 `504 Gateway Time-out` +- 较大的任务可能在模型网关返回 `504 Gateway Time-out` -### 8.3 推荐任务拆分方式 +### 10.3 推荐拆分方式 -为了让 sub mode 更稳定,建议把一个大任务拆成多个小任务,例如: +建议把一个大任务拆成多个小任务: - 先生成数据模型与 API 列表 -- 再生成 CRUD 路由代码骨架 -- 再生成 pytest 用例 -- 前端单独生成为组件与样式骨架 +- 再生成 CRUD 路由骨架 +- 再生成测试样例 +- 前端组件与样式单独生成 - reviewer 单独作为收尾检查任务 -不要一上来就发: - -- “生成完整后端项目” -- “生成完整前后端联调代码” -- “一次性给出所有页面、接口、测试和审查报告” - -## 9. 模型网关配置要求 - -这是当前最容易踩坑的地方。 +## 11. 模型网关配置要求 当前 runtime agent 需要一个真正返回模型 JSON 的 OpenAI 兼容基址。 @@ -443,9 +454,9 @@ https://code.xinghanlab.com - `HEICODE_NEWAPI_BASE_URL=https://code.xinghanlab.com/v1` - `LITELLM_BASE_URL=https://code.xinghanlab.com/v1` -## 10. 最小验证流程 +## 12. 最小验证流程 -### 10.1 服务与契约验证 +### 12.1 服务与契约验证 ```bash curl http://127.0.0.1:8000/api/agent/health @@ -453,7 +464,7 @@ curl http://127.0.0.1:8000/api/agnet/health PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest tests/test_sub_mode_runtime_contract.py -q ``` -### 10.2 真实 smoke 验证 +### 12.2 真实 smoke 验证 建议至少跑一条小型真实编程任务,例如: @@ -463,11 +474,12 @@ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest tests/test_sub_mode_runtime_c 成功标准: 1. 创建响应返回 `accepted` -2. 最终状态到 `completed` +2. Runtime 最终状态到 `completed` 3. `artifacts` 非空 4. `artifacts/{artifact_id}/content` 返回可读正文,而不是 UUID、HTML 或空串 +5. fallback artifact 必须带 `synthesized=true` / `summary_only=true` -## 11. 相关文件 +## 13. 相关文件 主入口与兼容入口: @@ -487,8 +499,9 @@ K8s 部署与配置: --- -如果接入方只想记最关键的三件事,只需要记: +如果接入方只想记最关键的四件事,只需要记: -1. 新接入统一走 `/api/agent/sub-agile/*` -2. 结果读取统一走 `deployment_id -> artifacts -> artifact content` -3. 模型网关基址必须是 `https://code.xinghanlab.com/v1` +1. 生产客户端只调用 Manager 的 `/api/heicode/*` +2. Manager 调 Runtime 统一走 `/api/agent/sub-agile/*` +3. Runtime `completed` 只是 runtime_execution_status,不等于最终 display_status +4. `summary_only=true` 的 artifact 不能直接当代码类任务有效交付物 diff --git a/docs/HEICODE_V2_1_4_UPDATE_SUMMARY.md b/docs/HEICODE_V2_1_4_UPDATE_SUMMARY.md index f20e608..5f25607 100644 --- a/docs/HEICODE_V2_1_4_UPDATE_SUMMARY.md +++ b/docs/HEICODE_V2_1_4_UPDATE_SUMMARY.md @@ -14,14 +14,14 @@ 核心变化: - `/api/swarms` 新增 Runtime 兼容入口,可接收 Heicode Manager 的结构化 `orchestration_plan`。 -- `/api/agnet/deployments` 支持普通 sub 结构化计划,并会主动发出 Runtime 生命周期 callback。 +- `/api/agent/sub-agile/deployments` 支持普通 sub 结构化计划,并会主动发出 Runtime 生命周期 callback。 - 修复普通 sub 真实执行后缺失 `artifact.created` 的问题,并补齐用户态 artifacts 可见性。 - 新增 `task.completed` / `task.failed` / `task.blocked` 事件,用于补齐普通 sub 子任务终态。 - 修复 deployment 已完成但 `agents[].status` 仍为 `running` 的状态不一致问题。 - `/api/swarms/{swarm_id}/logs` 不再返回 Phase 2 固定占位文本,而是输出 Runtime 聚合日志摘要。 - Callback 协议升级到 v2.1 形态,支持 HMAC 签名、幂等事件、`payload.*` 格式和旧 token 过渡兼容。 - 新增 artifact、timeline、SK snapshot 用户态查询接口,数据由 Runtime callback event 投影生成。 -- 新增审批 decision 接收路径,覆盖 `/api/swarms` 和 `/api/agnet/deployments` 两种运行入口。 +- 新增审批 decision 接收路径,覆盖 `/api/swarms` 和 `/api/agent/sub-agile/deployments` 两种运行入口。 - K8s/Docker 部署配置补充 Heicode、Vault、Redis、模型网关相关环境变量和代码目录。 --- @@ -55,10 +55,10 @@ 响应兼容: - `deployment_id` 与 `swarm_id` 同时返回;当前两者同值。 -- `/api/agnet/deployments/{deployment_id}` 可查询 `/api/swarms` 创建出的 run。 -- `/api/agnet/deployments/{deployment_id}/stop` 可停止 `/api/swarms` 创建出的 run。 +- `/api/agent/sub-agile/deployments/{deployment_id}` 可查询 `/api/swarms` 创建出的 run。 +- `/api/agent/sub-agile/deployments/{deployment_id}/stop` 可停止 `/api/swarms` 创建出的 run。 -### 2.2 `/api/agnet/deployments` 普通 sub 兼容 +### 2.2 `/api/agent/sub-agile/deployments` 普通 sub 兼容 创建部署现在可以直接接收结构化 `orchestration_plan`,并将字段提升到旧版模型: @@ -94,7 +94,7 @@ ### 3.1 Runtime 主动回调 -`/api/agnet/deployments` 和 `/api/swarms` 创建的任务会根据 `callback.subscribed_events` 主动推送事件。 +`/api/agent/sub-agile/deployments` 和 `/api/swarms` 创建的任务会根据 `callback.subscribed_events` 主动推送事件。 默认事件集: @@ -126,7 +126,7 @@ 新增接收接口: ```http -POST /api/agnet/callbacks/swarm-events +POST /api/agent/callbacks/runtime-events ``` 支持能力: @@ -142,7 +142,7 @@ POST /api/agnet/callbacks/swarm-events 联调 schema 接口: ```http -GET /api/agnet/callbacks/swarm-events/schema +GET /api/agent/callbacks/runtime-events/schema ``` 该接口只返回事件类型、分类、必填字段、阶段枚举和 artifact 类型,不返回 token 或明文密钥。 @@ -153,9 +153,9 @@ GET /api/agnet/callbacks/swarm-events/schema | 方法 | 路径 | 数据来源 | |------|------|----------| -| `GET` | `/api/agnet/user/deployments/{deployment_id}/artifacts` | `artifact.created` callback payload | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/timeline` | timeline、phase、agent、approval、budget、artifact、SK tool 事件合并 | -| `GET` | `/api/agnet/user/deployments/{deployment_id}/sk-snapshots` | `sk_tool.*` 与携带 `sk_snapshot` 的 artifact 事件 | +| `GET` | `/api/agent/user/deployments/{deployment_id}/artifacts` | `artifact.created` callback payload | +| `GET` | `/api/agent/user/deployments/{deployment_id}/timeline` | timeline、phase、agent、approval、budget、artifact、SK tool 事件合并 | +| `GET` | `/api/agent/user/deployments/{deployment_id}/sk-snapshots` | `sk_tool.*` 与携带 `sk_snapshot` 的 artifact 事件 | 注意:当前 artifact/timeline/SK snapshot 不是独立表字段化存储,而是由 callback event payload 投影生成。 @@ -168,7 +168,7 @@ GET /api/agnet/callbacks/swarm-events/schema | 场景 | 接口 | |------|------| | `/api/swarms` run | `POST /api/swarms/{swarm_id}/approvals/{approval_id}` | -| 普通 deployment | `POST /api/agnet/deployments/{deployment_id}/approvals/{approval_id}` | +| 普通 deployment | `POST /api/agent/sub-agile/deployments/{deployment_id}/approvals/{approval_id}` | decision 只接受: @@ -221,14 +221,14 @@ Docker 镜像: ## 7. 建议联调清单 -1. 调用 `GET /api/agnet/health` 确认服务可用。 -2. 调用 `GET /api/agnet/callbacks/swarm-events/schema` 确认 callback schema 与事件类型。 +1. 调用 `GET /api/agent/health` 确认服务可用。 +2. 调用 `GET /api/agent/callbacks/runtime-events/schema` 确认 callback schema 与事件类型。 3. 使用 `POST /api/swarms` 创建普通 sub 敏捷 run,并传入 `X-Idempotency-Key`。 4. 重复第 3 步确认幂等返回已有 run。 5. 使用缺失 `callback.url`、缺失 `user_context.user_id`、`dry_run:true` 的 payload 验证 `422`。 6. 查询 `/api/swarms/{swarm_id}` 和 `/api/swarms/{swarm_id}/status` 验证 `deployment_id` / `swarm_id` 兼容。 7. 验证普通 sub 实际执行后会收到 `task.completed` / `task.failed` 回调。 -8. 验证 Runtime 主动 callback 是否写入 `/api/agnet/user/deployments/{deployment_id}/timeline`。 +8. 验证 Runtime 主动 callback 是否写入 `/api/agent/user/deployments/{deployment_id}/timeline`。 9. 验证普通 sub 实际执行后会收到 `artifact.created`,并查询 artifacts 不再为 0。 10. 发送 `sk_tool.completed` 或带 `sk_snapshot` 的 artifact callback 后查询 SK snapshots。 11. 触发或模拟 `approval.requested` 后调用 approval decision 接口验证 `approved` / `rejected`。 diff --git a/k8s/agent-manager-deployment.yaml b/k8s/agent-manager-deployment.yaml index 8217b28..caf62b3 100644 --- a/k8s/agent-manager-deployment.yaml +++ b/k8s/agent-manager-deployment.yaml @@ -31,7 +31,7 @@ spec: containers: - name: agent-manager - image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601195848-arm64 + image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601225417-arm64 imagePullPolicy: Always ports: diff --git a/k8s/deployment-with-kubeconfig.yaml b/k8s/deployment-with-kubeconfig.yaml index 02e823a..a3ff689 100755 --- a/k8s/deployment-with-kubeconfig.yaml +++ b/k8s/deployment-with-kubeconfig.yaml @@ -22,7 +22,7 @@ spec: - name: acr-secret containers: - name: agent-manager - image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601195848-arm64 + image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601225417-arm64 imagePullPolicy: Always ports: - containerPort: 8000 diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index e0b191a..33103c5 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -20,7 +20,7 @@ spec: - name: acr-secret containers: - name: agent-manager - image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601195848-arm64 + image: agnettaiji.azurecr.io/ai-agents/agent-manager:heicode-v2-runtime-20260601225417-arm64 imagePullPolicy: Always ports: - containerPort: 8000 diff --git a/k8s_manager.py b/k8s_manager.py index 2c89fd1..6b15854 100644 --- a/k8s_manager.py +++ b/k8s_manager.py @@ -2466,7 +2466,10 @@ echo "Identity volume initialized successfully" or billing_context.get("timeout_seconds") or (600 if stream_enabled else 300) ) - max_tokens = int(billing_context.get("max_tokens") or 4096) + requested_max_tokens = int(billing_context.get("max_tokens") or 4096) + role_token_cap = 1600 if role in {"backend", "frontend", "coder", "engineer", "fullstack"} else 1200 + # Clamp per-agent output size to keep sub-mode runtime tasks stable on the gateway. + max_tokens = max(256, min(requested_max_tokens, role_token_cap)) # Get template image # TODO: Load from template database