Files
heicode/docs/integration/agnet-platform-request-contract.md
gongzhiyongandOmX bf134dec86 Make Agnet runs submit resource-scoped work safely
Manager now exposes a Resource Grant manifest and the Agnet control-plane response carries runtime state, agent instances, and permission_manifest so frontend runs can submit bounded resource grants without plaintext credentials.

Constraint: Manager remains the user console while NewAPI stays independent and OpenBao is referenced through secret_ref only.

Rejected: platform-side high-risk approval | client approval is the product boundary; Agnet only validates approval evidence.

Confidence: medium

Scope-risk: moderate

Directive: Do not mix child Agnet runtime model selection with NewAPI billing or expose OpenBao as a public route.

Tested: git diff --check; jq empty locale JSON; go vet ./controller ./model ./router; go test -count=1 ./controller ./model ./router

Not-tested: frontend typecheck/build because local node_modules tooling is absent and user requested builds happen on the VM.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-04 18:55:53 +08:00

962 lines
36 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Manager → Agnet 平台接口参数文档
**版本**: v0.3(P1/P5 联调契约)
**生效日期**: 2026-05-03
**状态**: 联调准备;当前仓库提供 Manager 侧最小验证端点,生产 Agnet 平台部署尚未在本文档中宣称完成。
**方向**: Heicode Manager 主动请求 Agnet 平台;Agnet 平台返回部署、日志、监控与审计状态。
**范围**: 创建/停止子 Agent 部署、查询部署、获取事件/日志/监控快照、解析 SK 快照、查询审计日志,以及 Agnet 辅助 NewAPI 重建/部署的参数约定。
> 2026-05-04 边界修正:Manager 当前不把 `tenant/project` 作为产品、认证或扣费主轴。新请求应使用 `user_context.user_id`、`user_context.channel_id`、`resource_grants[].binding_scope`、`billing_context(newapi)` 和 `agent_runtime(agnet)`。本文中仍出现的 `tenant_id/project_id` 只表示旧字段兼容或历史接口命名,不应作为新功能设计依据。
**安全红线**: 请求体只允许传资源元数据、权限范围与 `secret_ref`/环境变量名;不得传明文密码、Token、私钥、连接串或云访问密钥。
> 本文档描述 Manager 对 Agnet 平台的出站集成契约。当前仓库中 `/api/agnet/*` 是 Manager 侧最小控制面/模拟端点,用于校验同一套 payload 结构;生产接入时,Manager 应将下列请求发送到 Agnet 平台网关。
## 0. 概述
本文档按登录接口文档的对接方式组织:先定义接入信息,再逐个接口给出请求、响应、错误和安全约束。接口分组如下:
| 接口 | 用途 | 当前性质 |
|---|---|---|
| `POST /api/agnet/deployments` | 创建子 Agent/运维任务部署,含 NewAPI 重建/部署场景 | 必需 |
| `GET /api/agnet/deployments` | 查询部署列表 | 必需 |
| `GET /api/agnet/deployments/{deployment_id}` | 查询单个部署详情 | 必需 |
| `POST /api/agnet/deployments/{deployment_id}/stop` | 停止部署或取消排队任务 | 必需 |
| `GET /api/agnet/deployments/{deployment_id}/logs` | 拉取部署日志 | 必需 |
| `GET /api/agnet/deployments/{deployment_id}/logs/stream` | 实时日志 SSE | 可选 |
| `GET /api/agnet/projects/{project_id}/dashboard-snapshot` | 资源作用域监控快照;路径名保留旧兼容,参数值按 `binding_scope` 解释 | 必需 |
| `GET /api/agnet/deployments/{deployment_id}/metrics` | 单部署指标序列 | 建议 |
| `GET /api/agnet/deployments/{deployment_id}/events` | 部署事件 | 必需 |
| `GET /api/agnet/audit-logs` | 审计日志 | 必需 |
| `POST /api/agnet/sk-snapshots/resolve` | 触发 SK 快照解析 | 必需 |
| `GET /api/agnet/deployments/{deployment_id}/sk-snapshots` | 查询 SK 快照 | 必需 |
> 不在本文档范围:真实 Secret Store 写入、生产 SSH 登录、云账号授权回调、NewAPI 管理后台开放。生产部署动作只有实际执行并通过日志/监控/审计验证后,才能在报告中标记为“已部署”。
---
## 1. 接入约定
### 1.1 Base URL
由部署环境配置,不写入仓库。例如:
```text
AGNET_PLATFORM_BASE_URL=https://agnet-platform.example.com
```
联调环境建议使用独立域名或内网网关,示例不得包含真实凭据:
```text
AGNET_PLATFORM_BASE_URL=https://staging-agnet.example.com
MANAGER_SERVICE_TOKEN_SECRET_REF=vault://secret/users/manager-service/bindings/agnet-platform/service-token
```
完整路径示例:
```http
POST https://agnet-platform.example.com/api/agnet/deployments
```
### 1.2 通用 Header
| Header | 必填 | 说明 |
|---|---:|---|
| `Authorization: Bearer <manager-service-token>` | 是 | Manager 服务身份令牌,由 Secret Store/运行环境注入。 |
| `Content-Type: application/json` | POST/PUT 是 | JSON 请求体。 |
| `X-User-Id: <user_id>` | 建议 | 登录用户边界;也可从 Manager 服务端 token 或 body `user_context.user_id` 推导。 |
| `X-Binding-Scope: <binding_scope>` | 建议 | Git/SK/云资源作用域;也可从 `resource_grants[].binding_scope` 推导。 |
| `X-Correlation-Id: <uuid>` | 是 | Manager 生成,全链路追踪。 |
| `X-Request-Id: <uuid>` | 建议 | 单次 HTTP 请求追踪 ID,可与 correlation_id 不同。 |
| `Idempotency-Key: <uuid>` | 创建类接口建议 | 避免重试造成重复部署。 |
### 1.3 通用响应包裹
成功:
```json
{
"success": true,
"data": {}
}
```
失败:
```json
{
"success": false,
"message": "human readable message",
"error": {
"code": "POLICY_REJECTED",
"message": "human readable message",
"request_id": "req_xxx"
}
}
```
建议错误码:
| code | 场景 |
|---|---|
| `POLICY_REJECTED` | 缺必填字段、权限策略不满足、风险等级非法。 |
| `BUDGET_EXCEEDED` | 超过 token/金额/时长预算。 |
| `MODEL_NOT_ALLOWED` | agent 默认模型不在允许列表内。 |
| `FORBIDDEN_SCOPE` | Header 与 body/query 的用户或资源作用域不一致。 |
| `RESOURCE_GRANT_INVALID` | Resource Grant 字段缺失、跨用户/跨资源作用域/角色不匹配。 |
| `RESOURCE_GRANT_SECRET_REF_REQUIRED` | 凭据型资源缺少 `secret_ref`。 |
| `RESOURCE_GRANT_SECRET_REJECTED` | 请求中出现明文密钥字段。 |
| `SK_SOURCE_UNRESOLVABLE` | SK 来源不可解析。 |
| `DEPLOYMENT_CONFLICT` | 部署不存在、状态冲突或重复提交。 |
| `NOT_FOUND` | deployment、agent instance、snapshot 或审计资源不存在。 |
| `CURSOR_EXPIRED` | 分页游标过期或不属于当前查询条件。 |
| `RATE_LIMITED` | 平台限流;响应头建议包含 `Retry-After`。 |
| `INTERNAL_ERROR` | 平台内部错误;Manager 应记录 request_id 并重试或提示稍后处理。 |
### 1.4 通用错误处理
| HTTP | business code | Manager 处理建议 |
|---:|---|---|
| 400 | `POLICY_REJECTED` / `RESOURCE_GRANT_INVALID` | 标记部署失败,展示校验原因,不自动重试。 |
| 401 | `UNAUTHORIZED` | 检查 Manager 服务令牌的 `secret_ref`/环境注入,不把令牌写入日志。 |
| 403 | `FORBIDDEN_SCOPE` / `MODEL_NOT_ALLOWED` | 阻断本次部署,写审计事件。 |
| 404 | `NOT_FOUND` | 对查询类接口返回空态;对控制类接口提示资源不存在。 |
| 409 | `DEPLOYMENT_CONFLICT` | 使用 `Idempotency-Key` 查询既有结果,避免重复创建。 |
| 410 | `CURSOR_EXPIRED` | 丢弃 cursor,使用 `since` 重新拉取。 |
| 422 | `RESOURCE_GRANT_SECRET_REF_REQUIRED` / `RESOURCE_GRANT_SECRET_REJECTED` | 要求 Manager 重新生成只含 `secret_ref` 的 payload。 |
| 429 | `RATE_LIMITED` | 按 `Retry-After` 退避重试。 |
| 500/503 | `INTERNAL_ERROR` | 指数退避重试;超过阈值后转人工排查。 |
---
## 2. 创建子 Agent 部署
### 2.1 Endpoint
```http
POST /api/agnet/deployments
```
### 2.2 请求体
```json
{
"orchestration_plan": {
"intent_id": "intent_20260502_001",
"template_hint": "manager-resource-binding",
"objective": "为已绑定的代码仓库启动 builder 子 Agent,允许其读取 SK 并在限定路径内提交代码",
"risk_level": "low",
"budget": {
"max_tokens": 100000,
"max_cost_usd": 30,
"max_duration_sec": 7200
},
"user_context": {
"user_id": "user_123",
"email": "user@example.com",
"role": "user",
"channel_id": "channel_abc",
"subscription_tier": "pro"
},
"billing_context": {
"provider": "newapi",
"newapi_user_ref": "newapi_user_123",
"newapi_group": "development",
"quota_ref": "newapi_token_or_group_quota_ref"
},
"agent_runtime": {
"platform": "agnet",
"agents": [
{
"role": "builder",
"model_ref": "agnet_model_profile_builder",
"instance_count": 1
}
]
},
"constraints": {
"allowed_model_ids": ["gpt-5.4-mini", "gpt-5.4"]
},
"metadata": {
"tenant_id": "legacy-user-scope",
"project_id": "legacy-resource-scope",
"correlation_id": "corr_20260502_001"
},
"agents": [
{
"role_template": "builder",
"goal": "按 Manager 下发的任务在允许资源内完成实现、验证并回传状态",
"default_model_id": "gpt-5.4-mini",
"sk_sources": [
{
"type": "git",
"mime": "text/markdown",
"repo_ref": {
"connection_id": "conn_sk_repo_001",
"repo_url": "https://example.com/org/sk-repo.git",
"ref": "main",
"paths": ["skills/heicode/**", "AGENTS.md"]
}
}
],
"runtime_execution": {
"profile_id": "aks-codex-standard",
"cloud_principal_refs": ["principal://users/user_123/agnet-runtime"],
"network_policy_ref": "netpol://bindings/repo_default/restricted-egress"
},
"sk_access_policy": {
"policy_ref": "sk-policy://bindings/repo_default/default-readonly",
"deny_skill_ids": ["dangerous-shell"],
"inherit_deployment_defaults": true
},
"resource_grants": [
{
"grant_id": "grant_git_repo_001",
"resource_id": "res_git_repo_001",
"resource_type": "git",
"user_id": "user_123",
"binding_scope": "repo_default",
"tenant_id": "legacy-user-scope",
"project_id": "legacy-resource-scope",
"target_role": "builder",
"target_agent_ref": "agent-builder-1",
"permission_scope": ["repo:read", "repo:write:current-branch"],
"constraints": {
"ref": "main",
"allowed_paths": "heicode/**,docs/**",
"forbid_branch_create": "true"
},
"metadata": {
"provider": "gitee",
"repo_url": "https://example.com/org/repo.git"
},
"status": "active",
"secret_ref": "vault://secret/users/user_123/bindings/repo_default/resources/res_git_repo_001",
"audit": {
"created_by": "manager",
"approval_id": "approval_001"
}
},
{
"grant_id": "grant_doc_001",
"resource_id": "res_project_doc_001",
"resource_type": "project_doc",
"user_id": "user_123",
"binding_scope": "repo_default",
"tenant_id": "legacy-user-scope",
"project_id": "legacy-resource-scope",
"target_role": "builder",
"target_agent_ref": "agent-builder-1",
"permission_scope": ["doc:read"],
"constraints": {
"doc_paths": "docs/heicode.md,docs/plan.md"
},
"metadata": {
"doc_ref": "project-doc://project-a/docs-mainline"
},
"status": "active",
"audit": {
"created_by": "manager"
}
}
]
}
]
}
}
```
### 2.3 字段说明
#### orchestration_plan
| 字段 | 类型 | 必填 | 约束/说明 |
|---|---|---:|---|
| `intent_id` | string | 是 | Manager 侧意图 ID,用于幂等、审计和追踪。 |
| `template_hint` | string | 是 | Agnet 平台选择编排模板的提示,如 `manager-resource-binding`。 |
| `objective` | string | 是 | 本次部署目标,应是自然语言但不能含密钥。 |
| `risk_level` | enum | 是 | `low` / `medium` / `high`。高风险必须携带客户端审批证据;缺失或不匹配时只能只读或拒绝执行。 |
| `budget.max_tokens` | int | 是 | 当前策略上限建议不超过 `500000`。 |
| `budget.max_cost_usd` | number | 是 | 当前策略上限建议不超过 `200`。 |
| `budget.max_duration_sec` | int | 是 | 当前策略上限建议不超过 `86400`。 |
| `user_context` | object | 建议 | 登录用户上下文,优先使用 Heicode/Agnet 登录返回的 `user.id`/`channelId`。 |
| `billing_context` | object | 条件 | NewAPI 扣费上下文;只表达 user/token/group/quota 映射,不表达子 Agnet 模型或实例数。 |
| `agent_runtime` | object | 条件 | Agnet 平台运行时上下文;表达子 Agnet 角色、模型 profile 和实例数,不承载 NewAPI key 或扣费对象。 |
| `constraints.allowed_model_ids` | string[] | 否 | agent 的 `default_model_id` 如填写,必须在此列表内。 |
| `metadata.tenant_id` | string | 否 | 旧兼容字段;新实现不得作为产品租户边界。 |
| `metadata.project_id` | string | 否 | 旧兼容字段;新实现不得作为项目账本边界。 |
| `metadata.correlation_id` | string | 是 | 全链路追踪 ID。 |
| `agents` | array | 是 | 至少 1 个子 Agent。 |
#### user_context / billing_context / agent_runtime
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `user_context.user_id` | string | 建议 | Manager 业务用户 ID,来自登录接口 `id` 或 JWT `sub`。 |
| `user_context.channel_id` | string | 建议 | 用于关联 NewAPI 用户、Token、Group、余额或额度策略。 |
| `billing_context.provider` | enum | 条件 | 当前只允许 `newapi`。设置后必须提供 `channel_id`、`newapi_user_ref`、`newapi_group` 或 `quota_ref` 之一。 |
| `billing_context.newapi_user_ref` | string | 否 | NewAPI 用户映射引用,不是 NewAPI key。 |
| `billing_context.newapi_group` | string | 否 | NewAPI Group 映射,用于额度或策略选择。 |
| `billing_context.quota_ref` | string | 否 | Token 或 Group 额度引用,不得包含真实 Token 原文。 |
| `agent_runtime.platform` | enum | 条件 | 当前只允许 `agnet`。 |
| `agent_runtime.agents[].role` | string | 条件 | 必须匹配 `agents[].role_template`。 |
| `agent_runtime.agents[].model_ref` | string | 条件 | Agnet 平台模型 profile 引用;不是 NewAPI 扣费字段。 |
| `agent_runtime.agents[].instance_count` | int | 条件 | 子 Agnet 实例数量,必须大于 0。 |
#### agents[]
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `role_template` | string | 是 | 平台角色模板,如 `builder`/`reviewer`/`operator`。 |
| `goal` | string | 是 | 此 agent 的任务目标。 |
| `default_model_id` | string | 否 | 默认模型;若设置需满足 allowed_model_ids。 |
| `sk_sources` | array | 否 | SK 来源,平台应解析为只读快照。 |
| `runtime_execution` | object | 否 | 运行环境绑定;任一字段存在时 `profile_id` 必填。 |
| `sk_access_policy` | object | 否 | SK 权限策略。若 `deny_skill_ids` 非空,需 `policy_ref` 或继承默认策略。 |
| `resource_grants` | array | 否 | Manager 下发给子 Agent 的最小权限资源授权。 |
#### sk_sources[]
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `type` | enum | 否 | 空值表示不启用;支持 `git`、`upload`。 |
| `artifact_id` | string | upload 必填 | 上传型 SK 包 ID。 |
| `mime` | string | 否 | 内容类型,如 `text/markdown`。 |
| `repo_ref.connection_id` | string | git 建议 | Git 连接资源 ID。 |
| `repo_ref.repo_url` | string | git 建议 | 仓库 URL;不得带用户名密码。 |
| `repo_ref.ref` | string | git 必填 | 分支/标签/commit。 |
| `repo_ref.paths` | string[] | git 必填 | 允许读取的路径。 |
#### runtime_execution
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `profile_id` | string | 条件必填 | Agnet 平台运行规格,如 AKS profile。 |
| `cloud_principal_refs` | string[] | 否 | 运行身份引用,不是明文凭据。 |
| `network_policy_ref` | string | 否 | 网络策略引用,用于限制出站/入站。 |
#### resource_grants[]
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `grant_id` | string | 是 | 授权记录 ID。 |
| `resource_id` | string | 是 | Manager 资源 ID。 |
| `resource_type` | enum | 是 | `git` / `sk` / `project_doc` / `cloud_account` / `cloud_resource`。 |
| `user_id` | string | 建议 | 与 `user_context.user_id` 一致;为空时平台可从部署上下文推导。 |
| `binding_scope` | string | 是 | Git/SK/云资源作用域,例如 repo/ref/path 或云资源引用。 |
| `tenant_id` | string | 否 | 旧兼容字段;新实现不应依赖。 |
| `project_id` | string | 否 | 旧兼容字段;新实现不应依赖。 |
| `target_role` | string | 是 | 必须等于当前 agent 的 `role_template`。 |
| `target_agent_ref` | string | 是 | Manager 侧对子 Agent 的逻辑引用。 |
| `permission_scope` | string[] | 是 | 最小权限列表,如 `repo:read`、`doc:read`。 |
| `constraints` | object<string,string> | 否 | 路径、分支、区域、超时等限制;不得含密钥字段。 |
| `metadata` | object<string,string> | 否 | 资源展示/审计元数据;不得含密钥字段。 |
| `status` | enum | 是 | `pending` / `active` / `disabled` / `revoked`。 |
| `secret_ref` | string | 条件必填 | `git`、`sk`、`cloud_account`、`cloud_resource` 必填;`project_doc` 可为空。 |
| `audit` | object<string,string> | 否 | 审计上下文;不得含密钥字段。 |
### 2.4 典型场景:Agnet 辅助 NewAPI 重建/部署
当 Manager 需要让 Agnet 平台协助重建或部署 NewAPI 时,仍使用 `POST /api/agnet/deployments`,但必须把任务表达为受控运维部署,不得把 VM、PostgreSQL、Redis、NewAPI key 等真实凭据写入请求体。
请求体示例:
```json
{
"orchestration_plan": {
"intent_id": "intent_newapi_rebuild_20260503_001",
"template_hint": "newapi-rebuild-deploy",
"objective": "在批准窗口内重建 NewAPI 服务并回传健康检查、日志与资源使用摘要",
"risk_level": "high",
"budget": {
"max_tokens": 80000,
"max_cost_usd": 20,
"max_duration_sec": 3600
},
"constraints": {
"allowed_model_ids": ["gpt-5.4", "gpt-5.4-mini"],
"requires_approval": "true",
"rollback_required": "true",
"healthcheck_url_ref": "env://NEWAPI_HEALTHCHECK_URL"
},
"metadata": {
"tenant_id": "legacy-user-scope",
"project_id": "legacy-newapi-scope",
"correlation_id": "corr_newapi_20260503_001",
"service": "new-api",
"environment": "production",
"commit": "origin/main",
"runbook_ref": "heicode/docs/deploy/new-api-rebuild-deploy-runbook.md"
},
"agents": [
{
"role_template": "operator",
"goal": "按 runbook 执行构建、服务重启、健康检查和失败回滚;只通过 secret_ref/env 获取凭据",
"default_model_id": "gpt-5.4",
"runtime_execution": {
"profile_id": "aks-codex-ops",
"cloud_principal_refs": ["principal://users/user_123/agnet-ops"],
"network_policy_ref": "netpol://bindings/newapi-prod/ops-egress"
},
"resource_grants": [
{
"grant_id": "grant_newapi_vm_ops",
"resource_id": "res_newapi_vm",
"resource_type": "cloud_resource",
"user_id": "user_123",
"binding_scope": "newapi-prod",
"tenant_id": "legacy-user-scope",
"project_id": "legacy-newapi-scope",
"target_role": "operator",
"target_agent_ref": "agent-operator-1",
"permission_scope": ["vm:ssh:approved-window", "service:restart", "log:read", "healthcheck:read"],
"constraints": {
"approval_id": "approval_newapi_001",
"window": "2026-05-03T10:00:00Z/2026-05-03T11:00:00Z",
"rollback_command_ref": "runbook://newapi/rollback"
},
"metadata": {
"host_ref": "env://NEWAPI_VM_HOST",
"service_name": "new-api"
},
"status": "active",
"secret_ref": "vault://secret/users/user_123/bindings/newapi-prod/resources/res_newapi_vm",
"audit": {
"created_by": "manager",
"approval_id": "approval_newapi_001"
}
},
{
"grant_id": "grant_newapi_runtime_env",
"resource_id": "res_newapi_runtime_env",
"resource_type": "cloud_resource",
"user_id": "user_123",
"binding_scope": "newapi-prod",
"tenant_id": "legacy-user-scope",
"project_id": "legacy-newapi-scope",
"target_role": "operator",
"target_agent_ref": "agent-operator-1",
"permission_scope": ["env:read:runtime", "secret:read:scoped"],
"constraints": {
"allowed_env_refs": "DATABASE_DSN,REDIS_URL,NEWAPI_SERVICE_TOKEN",
"plaintext_export_forbidden": "true"
},
"metadata": {
"secret_provider": "openbao",
"scope": "newapi-runtime"
},
"status": "active",
"secret_ref": "vault://secret/users/user_123/bindings/newapi-prod/resources/res_newapi_runtime_env",
"audit": {
"created_by": "manager",
"approval_id": "approval_newapi_001"
}
}
]
}
]
}
}
```
Agnet 平台返回的部署详情、日志、监控和审计中应至少能证明:构建版本/commit、服务重启结果、健康检查结果、资源使用情况、失败回滚状态。未执行真实 SSH/生产动作时,只能返回 `phase=planned` 或 `phase=pending_approval`。
NewAPI 重建/部署的完成判定必须同时满足:
1. `metadata.commit` 或部署详情中的 resolved commit 已在 VM 仓库中生效。
2. 部署日志包含构建/compose/restart 的脱敏摘要。
3. 健康检查返回成功,且监控接口能返回本次 deployment 的状态或资源摘要。
4. 审计日志包含高风险审批 ID、执行者、目标环境和结果。
5. 回滚指针或回滚命令引用已记录。
### 2.5 成功响应
```json
{
"success": true,
"data": {
"deployment_id": "dep_abc123",
"status": "accepted",
"agent_instances": [
{
"instance_id": "agi_abc123",
"role": "builder",
"phase": "pending"
}
]
}
}
```
---
## 3. 部署状态与控制接口
### 3.1 查询部署列表
```http
GET /api/agnet/deployments?user_id=user_123&binding_scope=repo_default
```
返回:
```json
{
"success": true,
"data": {
"items": [
{
"deployment_id": "dep_abc123",
"status": "accepted",
"phase": "pending",
"created_at": "2026-05-02T00:00:00Z",
"updated_at": "2026-05-02T00:00:00Z"
}
],
"total": 1
}
}
```
### 3.2 查询单个部署
```http
GET /api/agnet/deployments/{deployment_id}
```
返回应包含部署状态、phase、agent_instances、最近错误、资源授权摘要和预算消耗摘要。Agnet 平台返回时必须对 `secret_ref` 以外的凭据信息做脱敏;原则上不返回任何明文凭据。
### 3.3 停止部署
```http
POST /api/agnet/deployments/{deployment_id}/stop
```
请求体可为空;如需原因可扩展:
```json
{
"reason": "user_requested",
"requested_by": "manager"
}
```
成功:
```json
{
"success": true,
"data": {
"deployment_id": "dep_abc123",
"status": "stopped"
}
}
```
错误与幂等:
| HTTP | business code | 说明 |
|---:|---|---|
| 200 | - | 已停止的部署重复停止也可返回 200,并保持 `status=stopped`。 |
| 404 | `NOT_FOUND` | 部署不存在或不属于当前租户/项目。 |
| 409 | `DEPLOYMENT_CONFLICT` | 部署已进入不可停止的终态,如 `completed` 且无运行实例。 |
| 422 | `POLICY_REJECTED` | 高风险停止缺少审批记录或 reason 不合法。 |
若停止请求触发异步回收,平台可返回 `status=stopping`;Manager 应继续通过事件、日志和监控接口确认最终状态。
---
## 4. 日志接口(Manager 拉取 Agnet 平台)
### 4.1 获取部署日志
```http
GET /api/agnet/deployments/{deployment_id}/logs?agent_instance_id=agi_abc123&stream=stdout&since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
```
Query:
| 参数 | 必填 | 说明 |
|---|---:|---|
| `agent_instance_id` | 否 | 不传则返回该 deployment 下全部实例日志。 |
| `stream` | 否 | `stdout` / `stderr` / `system` / `audit`,默认全部。 |
| `since` | 否 | RFC3339 时间,增量拉取起点。 |
| `limit` | 否 | 默认 200,建议最大 1000。 |
| `cursor` | 否 | 分页游标。 |
响应:
```json
{
"success": true,
"data": {
"items": [
{
"log_id": "log_001",
"deployment_id": "dep_abc123",
"agent_instance_id": "agi_abc123",
"stream": "stdout",
"level": "info",
"message": "task started",
"redacted": true,
"occurred_at": "2026-05-02T00:00:01Z"
}
],
"next_cursor": "cur_002",
"total": 1
}
}
```
日志要求:
- Agnet 平台必须在返回前完成密钥脱敏。
- `message` 不得包含密码、Token、私钥、连接串、云访问密钥。
- Manager 只保存必要摘要和审计索引;长日志建议落对象存储并设置保留期。
### 4.2 实时日志流(可选)
```http
GET /api/agnet/deployments/{deployment_id}/logs/stream?agent_instance_id=agi_abc123
Accept: text/event-stream
```
SSE event 示例:
```text
event: log
data: {"log_id":"log_002","level":"info","message":"step completed","occurred_at":"2026-05-02T00:00:02Z"}
```
SSE 事件类型:
| event | 说明 |
|---|---|
| `log` | 普通日志行,必须已脱敏。 |
| `heartbeat` | 保活事件,建议 15-30 秒一次。 |
| `error` | 流式读取错误;不包含敏感上下文。 |
| `done` | 部署进入终态或服务端主动结束流。 |
错误处理:
| HTTP | business code | Manager 处理建议 |
|---:|---|---|
| 401/403 | `UNAUTHORIZED` / `FORBIDDEN_SCOPE` | 立即断开流并记录审计。 |
| 404 | `NOT_FOUND` | 停止订阅并刷新部署详情。 |
| 429 | `RATE_LIMITED` | 退避后重连,保留 `Last-Event-Id`。 |
---
## 5. 监控接口(Manager 拉取 Agnet 平台)
### 5.1 项目监控快照
```http
GET /api/agnet/projects/{binding_scope}/dashboard-snapshot?window=1h
```
响应:
```json
{
"success": true,
"data": {
"project_id": "project-a",
"active_instances": 3,
"phase_distribution": {
"pending": 1,
"running": 2,
"stopped": 0,
"failed": 0
},
"failure_rate_1h": 0.02,
"avg_task_duration": 185.3,
"budget": {
"tokens_used": 32000,
"cost_usd": 4.21,
"duration_sec": 930
},
"resource_usage": {
"cpu_millicores": 1200,
"memory_mb": 2048,
"network_rx_bytes": 102400,
"network_tx_bytes": 204800
},
"updated_at": "2026-05-02T00:05:00Z"
}
}
```
### 5.2 单部署监控快照(建议平台实现)
```http
GET /api/agnet/deployments/{deployment_id}/metrics?window=15m&step=60s
```
响应:
```json
{
"success": true,
"data": {
"deployment_id": "dep_abc123",
"window": "15m",
"series": [
{
"metric": "tokens_used",
"unit": "count",
"points": [["2026-05-02T00:00:00Z", 1200]]
},
{
"metric": "cpu_millicores",
"unit": "millicore",
"points": [["2026-05-02T00:00:00Z", 500]]
}
]
}
}
```
建议指标:`tokens_used`、`cost_usd`、`duration_sec`、`cpu_millicores`、`memory_mb`、`restart_count`、`tool_call_count`、`error_count`、`queue_latency_ms`。
---
## 6. 事件与审计接口
### 6.1 部署事件
```http
GET /api/agnet/deployments/{deployment_id}/events?since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
```
响应:
```json
{
"success": true,
"data": {
"items": [
{
"event_id": "evt_001",
"event": "deployment.accepted",
"schema_version": 1,
"user_id": "user_123",
"channel_id": "channel_abc",
"binding_scope": "repo_default",
"deployment_id": "dep_abc123",
"correlation_id": "corr_20260502_001",
"occurred_at": "2026-05-02T00:00:00Z"
}
],
"next_cursor": "cur_002",
"total": 1
}
}
```
常用事件名:
| event | 说明 |
|---|---|
| `deployment.accepted` | 平台接受部署请求。 |
| `instance.phase_changed` | 子 Agent phase 变化。 |
| `sk_snapshot_refreshed` | SK 快照解析/刷新完成。 |
| `resource_grant.attached` | 资源授权已绑定到实例。 |
| `resource_grant.revoked` | 授权被撤销或禁用。 |
| `budget.threshold_reached` | 预算阈值触发。 |
| `deployment.failed` | 部署失败。 |
### 6.2 审计日志
```http
GET /api/agnet/audit-logs?user_id=user_123&binding_scope=repo_default&actor=agnet_control_plane&action=deployment.accepted&since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
```
响应:
```json
{
"success": true,
"data": {
"items": [
{
"audit_id": "aud_001",
"actor": "agnet_control_plane",
"action": "deployment.accepted",
"resource": "dep_abc123",
"user_id": "user_123",
"channel_id": "channel_abc",
"binding_scope": "repo_default",
"request_id": "req_001",
"correlation_id": "corr_20260502_001",
"result": "ok",
"occurred_at": "2026-05-02T00:00:00Z"
}
],
"next_cursor": "cur_002",
"total": 1
}
}
```
---
## 7. SK 快照接口
### 7.1 触发解析/刷新
```http
POST /api/agnet/sk-snapshots/resolve
```
请求:
```json
{
"deployment_id": "dep_abc123"
}
```
响应:
```json
{
"success": true,
"data": {
"deployment_id": "dep_abc123",
"items": [
{
"snapshot_id": "sks_001",
"deployment_id": "dep_abc123",
"user_id": "user_123",
"binding_scope": "repo_default",
"source_type": "git",
"source_ref": "main:skills/heicode/**@sha_xxx",
"resolved_at": "2026-05-02T00:00:00Z"
}
],
"total": 1
}
}
```
### 7.2 查询部署 SK 快照
```http
GET /api/agnet/deployments/{deployment_id}/sk-snapshots
```
Query:
| 参数 | 必填 | 说明 |
|---|---:|---|
| `user_id` | 建议 | 与 `X-User-Id` 或 deployment 的 `user_context.user_id` 一致。 |
| `binding_scope` | 建议 | 与 `X-Binding-Scope` 或 deployment 的资源授权作用域一致。 |
| `source_type` | 否 | `git` / `upload`,用于筛选。 |
| `limit` | 否 | 默认 100,最大 500。 |
| `cursor` | 否 | 分页游标。 |
成功响应:
```json
{
"success": true,
"data": {
"items": [
{
"snapshot_id": "sks_001",
"deployment_id": "dep_abc123",
"user_id": "user_123",
"binding_scope": "repo_default",
"source_type": "git",
"source_ref": "main:skills/heicode/**@sha_xxx",
"artifact_ref": "artifact://bindings/repo_default/sk/sks_001",
"checksum": "sha256:example-redacted",
"status": "ready",
"resolved_at": "2026-05-02T00:00:00Z"
}
],
"next_cursor": "cur_002",
"total": 1
}
}
```
错误处理:
| HTTP | business code | 说明 |
|---:|---|---|
| 404 | `NOT_FOUND` | deployment 不存在或不属于当前租户/项目。 |
| 410 | `CURSOR_EXPIRED` | cursor 过期,使用不带 cursor 的查询重拉。 |
| 422 | `SK_SOURCE_UNRESOLVABLE` | 快照来源不可解析,详情在事件/日志中查看。 |
---
## 8. 安全校验清单
Manager 发给 Agnet 平台前必须执行:
1. `user_id`、`binding_scope`、`target_role` 与部署计划一致。
2. 凭据型资源只传 `secret_ref`,不传明文凭据。
3. `metadata`、`constraints`、`audit` 的 key 中不得出现 `password`、`token`、`secret`、`private_key`、`access_key`、`credential` 等敏感词。
4. `repo_url` 不得包含用户名、密码或访问 Token。
5. `permission_scope` 使用最小权限;生产写操作必须携带客户端审批记录,Agnet 平台不得自行补批。
6. 高风险操作(生产部署、云资源修改、删除、扩容)必须设置 `risk_level=high`,Agnet 平台执行前只校验客户端审批证据。
7. 所有日志/事件/审计返回给 Manager 前必须脱敏。
Agnet 平台不承担高危操作审批主体。审批只发生在客户端;Agnet 平台只能在执行前校验以下字段和策略是否一致:
| 校验项 | 要求 |
|---|---|
| `approval_id` | 必须存在于高危任务的 `constraints` 或 `audit`,并可追溯到客户端审批记录。 |
| 审批主体 | 审批用户必须与 `user_context.user_id`、`resource_grants[].user_id` 或授权代理主体一致。 |
| 审批范围 | 审批范围必须覆盖 `binding_scope`、`permission_scope`、目标环境、资源 ID 和操作类型。 |
| TTL / 时间窗口 | 审批记录必须未过期;若使用 `window` 或 TTL,当前执行时间必须落在允许范围内。 |
| `risk_level` | 高危资源写入、生产部署、云资源修改、删除和扩容必须为 `high`。 |
| 策略 | 平台 policy、OpenBao policy、Kubernetes/Workload Identity、网络策略和最小权限约束均必须允许本次动作。 |
任一校验不通过时,Agnet 平台应返回 `POLICY_REJECTED` 或 `FORBIDDEN_SCOPE`,不得发起额外批准流程。
### 8.1 字段级约束速查
| 对象/接口 | 必填最小集合 | 禁止内容 |
|---|---|---|
| `orchestration_plan` | `intent_id`、`template_hint`、`objective`、`risk_level`、`budget`、`user_context`、`billing_context`、`agent_runtime`、`metadata.correlation_id`、`agents[]` | 密钥、连接串、真实主机登录密码、NewAPI key 原文。 |
| `agents[]` | `role_template`、`goal` | 让子 Agent 绕过 Manager/Agnet 审计的指令。 |
| `runtime_execution` | 任一字段存在时 `profile_id` 必填 | 明文 kubeconfig、SSH key、云访问密钥。 |
| `resource_grants[]` | `grant_id`、`resource_id`、`resource_type`、`user_id`、`binding_scope`、`target_role`、`target_agent_ref`、`permission_scope`、`status` | 明文 `password`、`token`、`private_key`、`access_key`、`credential`、数据库 DSN。 |
| 日志/事件/审计返回 | `request_id` 或 `correlation_id`,以及发生时间 | 未脱敏命令行、环境变量 dump、密钥片段。 |
| NewAPI 重建/部署场景 | `approval_id`、`rollback_command_ref`、健康检查引用、运行环境 `secret_ref` | 真实 VM 密码、PostgreSQL/Redis 连接串、NewAPI 服务令牌。 |
### 8.2 联调验收清单
- 创建部署请求只包含 `secret_ref`/`env://`/`runbook://` 引用,不包含真实凭据。
- `user_id` 与 `binding_scope` 在 user context、resource grant、事件和审计中一致。
- `risk_level=high` 的生产运维任务包含 `approval_id` 和回滚引用。
- 日志、事件、监控、审计接口都能通过 `correlation_id` 串联。
- NewAPI 重建/部署只在实际执行并通过健康检查后标记为已部署;未执行时状态只能是 `planned`、`pending_approval`、`accepted` 或 `running`。
- Manager 本地 `/api/agnet/*` 占位端点通过 payload 校验不等于生产 Agnet 平台已上线。
---
## 9. Manager 侧当前实现映射
当前代码中可用于对齐/验证 payload 的 Manager 侧端点:
| Manager 路由 | 用途 |
|---|---|
| `POST /api/agnet/deployments` | 校验并接受 orchestration_plan。 |
| `GET /api/agnet/deployments` | 按 user/binding scope 查询部署。 |
| `GET /api/agnet/deployments/:deployment_id` | 查询部署详情。 |
| `POST /api/agnet/deployments/:deployment_id/stop` | 停止部署。 |
| `GET /api/agnet/deployments/:deployment_id/logs` | 查询脱敏日志占位/联调日志。 |
| `GET /api/agnet/deployments/:deployment_id/metrics` | 查询单部署指标占位/联调指标。 |
| `GET /api/agnet/deployments/:deployment_id/events` | 查询事件。 |
| `POST /api/agnet/sk-snapshots/resolve` | 解析 SK 快照。 |
| `GET /api/agnet/deployments/:deployment_id/sk-snapshots` | 查询 SK 快照。 |
| `GET /api/agnet/projects/:project_id/dashboard-snapshot` | 资源作用域监控快照;路径名保留旧兼容。 |
| `GET /api/agnet/audit-logs` | 审计日志。 |
生产对接时,Manager 应把相同契约的请求发送给 Agnet 平台;本地 Manager 端点仅作为最小验证与控制面占位,不代表所有日志/监控平台能力已完整实现。
当前本地 `logs` 与 `metrics` 端点只返回脱敏占位/联调数据,用于验证 Manager ↔ Agnet payload、路由和验收流程。生产级实时日志流 `GET /api/agnet/deployments/{deployment_id}/logs/stream` 仍属于 Agnet 平台能力;Manager 不得把“本地占位通过”误报为“生产日志/监控已上线”。