From b38a89886e141ba19a30ac85b516cb1057307d4e Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:10:41 +0000 Subject: [PATCH 1/6] Accept an empty packages.system so a read Environment configuration round-trips --- contracts/agents-api/environments.md | 2 +- contracts/agents-api/harness-capabilities.md | 2 +- contracts/agents-api/index.md | 2 +- contracts/agents-api/zh/environments.md | 4 +-- .../agents-api/zh/harness-capabilities.md | 4 +-- contracts/agents-api/zh/index.md | 4 +-- .../internal/api/environment_packages_test.go | 11 +++++--- .../api/environment_preparation_input_test.go | 2 +- .../core/internal/api/environment_setup.go | 25 +++++++++++++------ 9 files changed, 36 insertions(+), 20 deletions(-) diff --git a/contracts/agents-api/environments.md b/contracts/agents-api/environments.md index 267de102c..61e996d46 100644 --- a/contracts/agents-api/environments.md +++ b/contracts/agents-api/environments.md @@ -222,7 +222,7 @@ Executor admission validates only the frozen descriptor. The preparation owner m The daemon runs as its launching account and never uses sudo or raises its permissions. Only user-directory dependencies install during preparation. - System dependencies must be preinstalled in the managed image or by the owner of a self-hosted machine. A missing executable or library fails the operation that needs it. -- `packages.system` is rejected in Templates and inline configuration, including a null or empty list (400, param `packages.system`). Package responses still carry the official required `system: []`. +- `packages.system` accepts null or an empty list, meaning no system packages, and rejects a nonempty list in Templates and inline configuration (400, param `packages.system`). Package responses carry the official required `system: []`, so a read configuration can be sent back unchanged. - npm installs into a local prefix and Python/pip into a local target under the Runtime package directory; Node/npm and Python/pip must already be installed. Their dependencies are visible to native tools in every working directory. - Setup commands run with Bash; on Windows, Git Bash is required and no other shell substitutes. The default working directory is `/workspace`. - On Windows, npm installation and stdio MCP commands named `npm` or `npx` (including their `.cmd` shims) run through npm's JavaScript entry point with Node, without an extra shell. diff --git a/contracts/agents-api/harness-capabilities.md b/contracts/agents-api/harness-capabilities.md index ad446300e..ee52be4d1 100644 --- a/contracts/agents-api/harness-capabilities.md +++ b/contracts/agents-api/harness-capabilities.md @@ -59,7 +59,7 @@ These operations need a workspace, so they apply to hosted and self-hosted place | [Initial files, setup commands, Skills and Plugins](./environments.md#runtime-capability-preparation) | Verified: hosted, self-hosted | Verified: self-hosted; admitted: hosted | Verified: self-hosted; admitted: hosted | | Capability directories | Admitted | Admitted | Admitted | | npm and Python packages | Admitted | Admitted | Admitted | -| `packages.system` | Rejected | Rejected | Rejected | +| `packages.system` | Rejected when nonempty | Rejected when nonempty | Rejected when nonempty | | Network `disabled` or `restricted` | Rejected | Rejected | Rejected | | [Plugin MCP over stdio](./environments.md#plugin-mcp) | Verified: hosted, self-hosted | Verified: self-hosted; admitted: hosted | Verified: self-hosted; admitted: hosted | | Plugin MCP over HTTP | Admitted, with literal headers or HTTPS bearer | Admitted, with literal headers or HTTPS bearer | Verified: self-hosted; admitted: hosted; literal headers or HTTPS bearer | diff --git a/contracts/agents-api/index.md b/contracts/agents-api/index.md index f653f559a..b33523076 100644 --- a/contracts/agents-api/index.md +++ b/contracts/agents-api/index.md @@ -139,7 +139,7 @@ Each item is Core's deliberate or native behavior where the official service beh - Hosted workspace admission is limited by the [tenant capacity policy](../../docs/configuration.md#tenant-capacity) and the [input reservation deadline](./environments.md#reservations). - MiniMax Code does not declare `retained_native_history`, so it cannot run on microsandbox, which keeps every Environment on workspace storage; Core rejects the Session ([Harness capabilities](./harness-capabilities.md)). - Only `enabled` networking runs, so Sessions that need `disabled` or `restricted` are rejected ([restricted network policy](./environments.md#restricted-network)). -- `packages.system` is rejected; system packages must be preinstalled. +- A nonempty `packages.system` is rejected; system packages must be preinstalled. - Cold continuation does not restore process memory, background processes or temporary system-disk changes, and completed setup is not replayed ([Environment persistence](./environments.md#runtime-capability-preparation)). On compatible microsandbox nodes with retained NFS storage, Codex and Claude Code are qualified for [checkpoint transfer](../../docs/sandbox-provider.md#checkpoint-transfer) and for continuation after [confirmed compute loss](../../docs/sandbox-provider.md#confirmed-compute-loss). Takeover of an unconfirmed old writer, host-crash durability and arbitrary crash-damaged history are unqualified. **Files and Environment files** diff --git a/contracts/agents-api/zh/environments.md b/contracts/agents-api/zh/environments.md index a663bb140..a8dd49d11 100644 --- a/contracts/agents-api/zh/environments.md +++ b/contracts/agents-api/zh/environments.md @@ -1,7 +1,7 @@ --- title: "Environment 与模板" source: contracts/agents-api/environments.md -source_hash: 6b609956acde1748bfc1762ba5428959a88de8b42cbcaa9297fb89c1c2c013bb +source_hash: 2a2b2dd17bcd90fa1c4c261da8d109404314b723d43329042070e4179d00d810 --- Environment 是 Session 的执行资源,包括 Harness 运行所在的机器、工作区以及已完成准备的能力。Session 通过其 `environment` 配置创建 Environment;不存在独立的 create 调用。Environment 模板是 Session 创建时解析的可复用准备配置。本契约涵盖这两类资源、两种放置方式、输入接纳、能力准备、Skills、Plugins 和 MCP 连接来源。 @@ -224,7 +224,7 @@ Executor 接纳仅验证已冻结的描述符。准备所有者会在调用原 daemon 以启动它的账户身份运行,绝不使用 sudo 或提升权限。准备过程中只会安装用户目录中的依赖项。 - 系统依赖必须预先安装在托管镜像中,或由自托管机器的所有者安装。缺少可执行文件或库时,需要该依赖的操作会失败。 -- 模板和内联配置都会拒绝 `packages.system`,包括 null 或空列表(400,param `packages.system`)。软件包响应仍会包含官方要求的 `system: []`。 +- `packages.system` 接受 null 或空列表(表示没有系统软件包),模板和内联配置会拒绝非空列表(400,param `packages.system`)。软件包响应包含官方要求的 `system: []`,因此读取到的配置可以原样回传。 - npm 会安装到本地 prefix,Python/pip 会安装到 Runtime 软件包目录下的本地 target;Node/npm 和 Python/pip 必须已经安装。其依赖项可被每个工作目录中的原生工具看到。 - 设置命令使用 Bash 运行;在 Windows 上必须使用 Git Bash,且不能由其他 shell 替代。默认工作目录为 `/workspace`。 - 在 Windows 上,npm 安装以及名为 `npm` 或 `npx` 的 stdio MCP 命令(包括其 `.cmd` shim)会通过 Node 调用 npm 的 JavaScript 入口点运行,而不经过额外的 shell。 diff --git a/contracts/agents-api/zh/harness-capabilities.md b/contracts/agents-api/zh/harness-capabilities.md index 0470a3c18..89012f5be 100644 --- a/contracts/agents-api/zh/harness-capabilities.md +++ b/contracts/agents-api/zh/harness-capabilities.md @@ -1,7 +1,7 @@ --- title: "Harness 能力" source: contracts/agents-api/harness-capabilities.md -source_hash: 507c77c74145cac386ac8dd0e231d5701821c00490c0c5db2d25f052911a3107 +source_hash: bd03ebf9e556b71091fed42d1ba52b2002207962ccc4f7c3765104c82bddc3b5 --- 本页列出每个 Harness 在每种部署位置支持的能力。Core 根据 `internal/harnessconfig//declaration.go` 中 Harness 的声明决定准入,运行 Session 的 Runtime 也必须声明操作。所链接契约定义各操作;[Harness 接入](harness-onboarding.md#qualify-the-adapter)说明资格验证方法。 @@ -61,7 +61,7 @@ Claude 结构化输出要求 medium verbosity,可与 `multi_agent`、Skill、P | [初始文件、设置命令、Skill 与 Plugin](environments.md#runtime-capability-preparation) | 已验证:托管、自托管 | 已验证:自托管;已准入:托管 | 已验证:自托管;已准入:托管 | | 能力目录 | 已准入 | 已准入 | 已准入 | | npm 与 Python 包 | 已准入 | 已准入 | 已准入 | -| `packages.system` | 已拒绝 | 已拒绝 | 已拒绝 | +| `packages.system` | 非空时拒绝 | 非空时拒绝 | 非空时拒绝 | | 网络 `disabled` 或 `restricted` | 已拒绝 | 已拒绝 | 已拒绝 | | [stdio Plugin MCP](environments.md#plugin-mcp) | 已验证:托管、自托管 | 已验证:自托管;已准入:托管 | 已验证:自托管;已准入:托管 | | HTTP Plugin MCP | 已准入,字面值头或 HTTPS bearer | 已准入,字面值头或 HTTPS bearer | 已验证:自托管;已准入:托管;字面值头或 HTTPS bearer | diff --git a/contracts/agents-api/zh/index.md b/contracts/agents-api/zh/index.md index cfa35b171..b757d2d2c 100644 --- a/contracts/agents-api/zh/index.md +++ b/contracts/agents-api/zh/index.md @@ -1,7 +1,7 @@ --- title: "OpenAI 兼容性" source: contracts/agents-api/index.md -source_hash: ae8f903f342adedb090dc95ff325796adef0c25f6ff1e67478b3c312901b28ee +source_hash: 45ccd7e7fce53589dbf27fc82e75b59b61fffe5fc40a3bbbb8003a8dfd230cba --- Core 实现下方固定版本的 OpenAI Agents API。本台账列出各项资源的覆盖情况、相对于官方服务的所有差异以及已知缺口。 @@ -142,7 +142,7 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh - Hosted 工作区准入受[租户容量策略](../../../docs/zh/configuration.md#tenant-capacity)及既有[输入预留截止时间](environments.md#reservations)限制。 - MiniMax Code 未声明 `retained_native_history`,因此无法在 microsandbox 上运行(其每个 Environment 都使用工作区存储);Core 会拒绝该 Session([Harness 能力](./harness-capabilities.md))。 - 只有 `enabled` 网络可以运行,因此需要 `disabled` 或 `restricted` 的 Session 会被拒绝([restricted network policy](environments.md#restricted-network))。 -- `packages.system` 会被拒绝;系统软件包必须预先安装。 +- 非空的 `packages.system` 会被拒绝;系统软件包必须预先安装。 - 冷续接不恢复进程内存、后台进程或临时系统盘修改,已完成的 setup 不会重放(参见 [Environment 持久化](environments.md#runtime-capability-preparation))。在使用保留 NFS 存储的兼容 microsandbox 节点上,Codex 和 Claude Code 已通过[检查点转移](../../../docs/zh/sandbox-provider.md#checkpoint-transfer)以及[已确认的计算丢失](../../../docs/zh/sandbox-provider.md#confirmed-compute-loss)后续接的资格验证。接管未确认停止的旧写入者、主机崩溃时的持久性及任意崩溃受损历史的完整性仍未通过资格验证。 **Files 和 Environment files** diff --git a/services/core/internal/api/environment_packages_test.go b/services/core/internal/api/environment_packages_test.go index 454c45983..bd350dec2 100644 --- a/services/core/internal/api/environment_packages_test.go +++ b/services/core/internal/api/environment_packages_test.go @@ -10,7 +10,7 @@ import ( ) func TestSystemPackagesRejectedAtEveryInput(t *testing.T) { - for _, value := range []string{`null`, `[]`, `["jq"]`} { + for _, value := range []string{`["jq"]`} { packages := `"packages":{"npm":["semver"],"python":["packaging"],"system":` + value + `}` t.Run(value, func(t *testing.T) { if _, err := decodeTemplateInput([]byte("{" + packages + "}")); !errors.Is(err, errSystemPackages) { @@ -29,8 +29,13 @@ func TestSystemPackagesRejectedAtEveryInput(t *testing.T) { } }) } - if _, err := decodeTemplateInput([]byte(`{"packages":{"npm":["semver"],"python":["packaging"]}}`)); err != nil { - t.Fatal("supported package managers rejected", err) + for _, system := range []string{``, `,"system":null`, `,"system":[]`} { + if _, err := decodeTemplateInput([]byte(`{"packages":{"npm":["semver"],"python":["packaging"]` + system + `}}`)); err != nil { + t.Fatal("supported package managers or an empty system list rejected", system, err) + } + if _, err := decodeSessionEnvironment(json.RawMessage(`{"type":"openai_hosted","packages":{"npm":["semver"]` + system + `}}`)); err != nil { + t.Fatal("Session rejected an empty system list", system, err) + } } } diff --git a/services/core/internal/api/environment_preparation_input_test.go b/services/core/internal/api/environment_preparation_input_test.go index 8904e087c..659049161 100644 --- a/services/core/internal/api/environment_preparation_input_test.go +++ b/services/core/internal/api/environment_preparation_input_test.go @@ -46,7 +46,7 @@ func TestPreparationExtensionRejectsAmbiguousAndPlacementInput(t *testing.T) { `{"environment":{"type":"self_hosted","workspace_directory":"/work"},"x_agents_core":{"environment":{"workspace_directory":"/other"}}}`, `{"environment":{"type":"self_hosted","workspace_directory":"/work","capability_directories":[]},"x_agents_core":{"environment":{"capability_directories":[]}}}`, `{"environment":{"type":"openai_hosted","env":null},"x_agents_core":{"environment":{"env":{"KEY":"value"}}}}`, - `{"environment":{"type":"self_hosted","workspace_directory":"/work"},"x_agents_core":{"environment":{"packages":{"system":[]}}}}`, + `{"environment":{"type":"self_hosted","workspace_directory":"/work"},"x_agents_core":{"environment":{"packages":{"system":["jq"]}}}}`, } { var request decodedSessionRequest if err := json.Unmarshal([]byte(input), &request); err != nil { diff --git a/services/core/internal/api/environment_setup.go b/services/core/internal/api/environment_setup.go index 1ec72d077..8e0958841 100644 --- a/services/core/internal/api/environment_setup.go +++ b/services/core/internal/api/environment_setup.go @@ -16,10 +16,20 @@ var errSystemPackages = &fieldError{ func rejectSystemPackages(raw json.RawMessage) error { var packages map[string]json.RawMessage - if json.Unmarshal(raw, &packages) == nil { - if _, supplied := packages["system"]; supplied { - return errSystemPackages - } + if json.Unmarshal(raw, &packages) != nil { + return nil + } + // The official schema reads back `system: []`, so null and an empty list mean none. + value, supplied := packages["system"] + if !supplied { + return nil + } + var system []json.RawMessage + if json.Unmarshal(value, &system) != nil { + return sessions.ErrInvalidInput + } + if len(system) != 0 { + return errSystemPackages } return nil } @@ -67,10 +77,11 @@ func decodeEnvironmentSetup(fields map[string]json.RawMessage) (environmentconfi } if value, ok := fields["packages"]; ok && !bytes.Equal(bytes.TrimSpace(value), []byte("null")) { var input struct { - NPM []*string `json:"npm"` - Python []*string `json:"python"` + NPM []*string `json:"npm"` + Python []*string `json:"python"` + System json.RawMessage `json:"system"` // checked by rejectSystemPackages } - if decodeInputObject(value, &input, "npm", "python") != nil { + if decodeInputObject(value, &input, "npm", "python", "system") != nil { return result, sessions.ErrInvalidInput } for name, entries := range map[string][]*string{"npm": input.NPM, "python": input.Python} { From e05e597fef4bc2fee3fade670c82af289bb69cf1 Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:13:17 +0000 Subject: [PATCH 2/6] Raise the events per request bound to the official 16384 --- contracts/agents-api/environments.md | 2 +- contracts/agents-api/sessions-events.md | 4 ++-- contracts/agents-api/zh/environments.md | 4 ++-- contracts/agents-api/zh/sessions-events.md | 6 +++--- services/core/internal/api/inputs.go | 4 ++-- services/core/internal/sessions/inputs.go | 16 ++++++++-------- services/core/internal/sessions/inputs_test.go | 14 ++++++++++++-- 7 files changed, 30 insertions(+), 20 deletions(-) diff --git a/contracts/agents-api/environments.md b/contracts/agents-api/environments.md index 61e996d46..44e56e033 100644 --- a/contracts/agents-api/environments.md +++ b/contracts/agents-api/environments.md @@ -106,7 +106,7 @@ The application owns the machine. It creates the Session with a clean absolute ` ## Input admission -Session input goes through `POST /agents/sessions/{id}/events` in ordered batches of 1–64 events. On an Environment-bearing Session, Core reserves input that cannot start yet until the Environment is connected and prepared. +Session input goes through `POST /agents/sessions/{id}/events` in ordered batches of 1–16384 events. On an Environment-bearing Session, Core reserves input that cannot start yet until the Environment is connected and prepared. A valid node-backed creation can wait for compute capacity after committing. Initial input uses the same reservation and deadline while waiting; creating without input still requests Environment preparation. [Placement and generation selection](./sandbox-deployment.md#generation-ownership-and-rollout) define the scheduling rules. diff --git a/contracts/agents-api/sessions-events.md b/contracts/agents-api/sessions-events.md index b56910b2a..f5261daa0 100644 --- a/contracts/agents-api/sessions-events.md +++ b/contracts/agents-api/sessions-events.md @@ -43,9 +43,9 @@ A Session stays usable after a Turn fails: new input starts a new Turn. Later re ## Send input -`POST /v1/agents/sessions/{session_id}/events` takes an ordered array of 1 to 64 events: `agent.session.input.message`, `agent.session.input.cancel` and `agent.session.input.tool_result`. The whole batch is admitted atomically, and the response is 202 with no body once the batch is stored, before any Harness reads it. Admission never confirms native application. +`POST /v1/agents/sessions/{session_id}/events` takes an ordered array of 1 to 16384 events: `agent.session.input.message`, `agent.session.input.cancel` and `agent.session.input.tool_result`. The whole batch is admitted atomically, and the response is 202 with no body once the batch is stored, before any Harness reads it. Admission never confirms native application. -- **Limits.** The request body is at most 1 MiB, and the stored input of one request at most 512 KiB. +- **Limits.** The request body is at most 4 MiB, and the stored input of one request at most 2 MiB. - **Null batch.** An explicit `null` for `events` is invalid. - **Empty batch.** `{"events": []}` checks that the Session exists and returns 202. It creates no Turn, Item or retry identity. - **Retries.** An `Idempotency-Key` of up to 128 bytes identifies the whole ordered batch. The same key and batch return 202 again without admitting anything twice; the same key with another batch returns 409 `idempotency_conflict`. A request without a key is always new. diff --git a/contracts/agents-api/zh/environments.md b/contracts/agents-api/zh/environments.md index a8dd49d11..11257f0be 100644 --- a/contracts/agents-api/zh/environments.md +++ b/contracts/agents-api/zh/environments.md @@ -1,7 +1,7 @@ --- title: "Environment 与模板" source: contracts/agents-api/environments.md -source_hash: 2a2b2dd17bcd90fa1c4c261da8d109404314b723d43329042070e4179d00d810 +source_hash: 826b3d0c74ea82af5c4f7e6094b71257a7e56fba896d5fc8a58234bc3bed5249 --- Environment 是 Session 的执行资源,包括 Harness 运行所在的机器、工作区以及已完成准备的能力。Session 通过其 `environment` 配置创建 Environment;不存在独立的 create 调用。Environment 模板是 Session 创建时解析的可复用准备配置。本契约涵盖这两类资源、两种放置方式、输入接纳、能力准备、Skills、Plugins 和 MCP 连接来源。 @@ -108,7 +108,7 @@ Core 在 Session 创建事务中创建 Environment 记录;Session upsert 会 ## 输入接纳 {#input-admission} -Session 输入通过 `POST /agents/sessions/{id}/events` 以每次 1–64 个事件的有序批次提交。对于带 Environment 的 Session,Core 会将尚不能启动的输入预留,直到 Environment 完成连接和准备。 +Session 输入通过 `POST /agents/sessions/{id}/events` 以每次 1–16384 个事件的有序批次提交。对于带 Environment 的 Session,Core 会将尚不能启动的输入预留,直到 Environment 完成连接和准备。 有效的节点模式创建可以在提交后等待计算容量。初始输入在等待期间仍使用同一 reservation 和期限;无输入创建也会请求 Environment 准备。[Placement 与代次选择](./sandbox-deployment.md#generation-ownership-and-rollout) 定义调度规则。 diff --git a/contracts/agents-api/zh/sessions-events.md b/contracts/agents-api/zh/sessions-events.md index 2ccb30548..a0ba61cb4 100644 --- a/contracts/agents-api/zh/sessions-events.md +++ b/contracts/agents-api/zh/sessions-events.md @@ -1,7 +1,7 @@ --- title: "Session、事件和历史" source: contracts/agents-api/sessions-events.md -source_hash: 45b743284c8a03aa016c1b874f6dbeb578e7ec7afcbc565bdcafba333481c950 +source_hash: 2984a8001807449fb923cecbd50fae872c1de9a4a1575ebb055d155b32c361ed --- 本契约涵盖 Session 内部发生的事情:发送输入、实时事件流,以及读取 Turn、Item 和使用量的持久化历史。Session 资源本身(创建配置、重试标识、更新、列出和删除)见 [API 行为](wire-semantics.md)。消息和函数结果内容见[消息内容](message-content.md)。[Agents API 指南](../../../docs/zh/api/public-agent-api.md)展示了使用 SDK 和 HTTP 的调用方式。 @@ -45,9 +45,9 @@ Turn 失败后 Session 仍可使用:新输入会启动一个新 Turn。后来 ## 发送输入 {#send-input} -`POST /v1/agents/sessions/{session_id}/events` 接收包含 1 到 64 个事件的有序数组:`agent.session.input.message`、`agent.session.input.cancel` 和 `agent.session.input.tool_result`。整个批次以原子方式接纳;批次存储后且在任何 Harness 读取它之前,响应为无正文的 202。接纳绝不表示已在原生侧应用。 +`POST /v1/agents/sessions/{session_id}/events` 接收包含 1 到 16384 个事件的有序数组:`agent.session.input.message`、`agent.session.input.cancel` 和 `agent.session.input.tool_result`。整个批次以原子方式接纳;批次存储后且在任何 Harness 读取它之前,响应为无正文的 202。接纳绝不表示已在原生侧应用。 -- **限制。** 请求正文最多为 1 MiB,单次请求存储的输入最多为 512 KiB。 +- **限制。** 请求正文最多为 4 MiB,单次请求存储的输入最多为 2 MiB。 - **空值批次。** 将 `events` 显式设为 `null` 无效。 - **空批次。** `{"events": []}` 会检查 Session 是否存在并返回 202。它不会创建 Turn、Item 或重试标识。 - **重试。** 最长 128 字节的 `Idempotency-Key` 标识整个有序批次。相同密钥和批次会再次返回 202,而不会重复接纳任何内容;相同密钥搭配另一个批次会返回 409 `idempotency_conflict`。不带密钥的请求始终是新请求。 diff --git a/services/core/internal/api/inputs.go b/services/core/internal/api/inputs.go index 8f38a4404..98d476978 100644 --- a/services/core/internal/api/inputs.go +++ b/services/core/internal/api/inputs.go @@ -21,7 +21,7 @@ type InputAdmission interface { } func (h *Handler) createEvents(w http.ResponseWriter, r *http.Request) { - raw, ok := readJSONObject(w, r) + raw, ok := readJSONObjectLimit(w, r, 4<<20, "Request exceeds 4 MiB.") if !ok { return } @@ -77,7 +77,7 @@ func (h *Handler) createEvents(w http.ResponseWriter, r *http.Request) { } func executionInputs(events []json.RawMessage) ([]sessions.Input, error) { - if len(events) == 0 || len(events) > 64 { + if len(events) == 0 || len(events) > 16384 { return nil, sessions.ErrInvalidInput } inputs := make([]sessions.Input, 0, len(events)) diff --git a/services/core/internal/sessions/inputs.go b/services/core/internal/sessions/inputs.go index c2159017d..b8f730883 100644 --- a/services/core/internal/sessions/inputs.go +++ b/services/core/internal/sessions/inputs.go @@ -39,21 +39,21 @@ func ValidateInputKey(key string) error { return nil } -// ValidateInputs checks and normalizes an input batch: 1..64 messages, -// cancellations and function results whose nonempty JSON object payloads total -// at most 512 KiB, an empty cancellation payload and a well-formed function -// result. It returns the normalized batch and its encoding, the batch's retry +// ValidateInputs checks and normalizes an input batch: 1..16384 messages (the +// official events bound), cancellations and function results whose nonempty +// JSON object payloads total at most 2 MiB, which fits 16384 minimal messages, +// an empty cancellation payload and a well-formed function result. It returns the normalized batch and its encoding, the batch's retry // identity. func ValidateInputs(inputs []Input) ([]Input, json.RawMessage, error) { - if len(inputs) == 0 || len(inputs) > 64 { - return nil, nil, fmt.Errorf("%w: input batch must contain 1..64 events", ErrInvalidInput) + if len(inputs) == 0 || len(inputs) > 16384 { + return nil, nil, fmt.Errorf("%w: input batch must contain 1..16384 events", ErrInvalidInput) } batch := make([]Input, len(inputs)) size := 0 for i, input := range inputs { size += len(input.Payload) - if size > 512*1024 || len(input.Payload) == 0 || (input.Kind != "message" && input.Kind != "cancel" && input.Kind != "tool_result") { - return nil, nil, fmt.Errorf("%w: input payloads must be nonempty and total at most 512 KiB", ErrInvalidInput) + if size > 2<<20 || len(input.Payload) == 0 || (input.Kind != "message" && input.Kind != "cancel" && input.Kind != "tool_result") { + return nil, nil, fmt.Errorf("%w: input payloads must be nonempty and total at most 2 MiB", ErrInvalidInput) } payload, err := jsonobject.Normalize(input.Payload) if err != nil { diff --git a/services/core/internal/sessions/inputs_test.go b/services/core/internal/sessions/inputs_test.go index d847b3f82..c2884b5d0 100644 --- a/services/core/internal/sessions/inputs_test.go +++ b/services/core/internal/sessions/inputs_test.go @@ -136,12 +136,12 @@ func TestValidateInputs(t *testing.T) { } for name, inputs := range map[string][]Input{ "no inputs": nil, - "65 inputs": make([]Input, 65), + "16385 inputs": make([]Input, 16385), "unsupported kind": {messageInput("ok"), {Kind: "unsupported", Payload: json.RawMessage(`{}`)}}, "missing payload": {{Kind: "message"}}, "array payload": {{Kind: "message", Payload: json.RawMessage(`[]`)}}, "cancel with a target": {{Kind: "cancel", Payload: json.RawMessage(`{"target":"other"}`)}}, - "over 512 KiB": {messageInput(strings.Repeat("x", 300*1024)), messageInput(strings.Repeat("y", 300*1024))}, + "over 2 MiB": {messageInput(strings.Repeat("x", 1200*1024)), messageInput(strings.Repeat("y", 1200*1024))}, } { if _, _, err := ValidateInputs(inputs); !errors.Is(err, ErrInvalidInput) { t.Errorf("%s: %v", name, err) @@ -149,6 +149,16 @@ func TestValidateInputs(t *testing.T) { } } +func TestValidateInputsFitsTheOfficialMaximum(t *testing.T) { + inputs := make([]Input, 16384) + for i := range inputs { + inputs[i] = messageInput("a") + } + if _, _, err := ValidateInputs(inputs); err != nil { + t.Fatal(err) + } +} + func TestValidateMessageInputs(t *testing.T) { if _, encoded, err := validateMessageInputs([]Input{messageInput("hi")}); err != nil || string(encoded) != `[{"kind":"message","payload":`+hi+`}]` { t.Fatalf("batch %s, %v", encoded, err) From fa9410723ba7003c2d325000a8ed2c1a59b1965b Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:15:11 +0000 Subject: [PATCH 3/6] Declare the MiniMax Code instructions limit and check it at admission --- apps/daemon/internal/agent/mcode/options.go | 3 --- .../daemon/internal/agent/mcode/options_test.go | 1 - contracts/agents-api/harness-onboarding.md | 2 +- contracts/agents-api/zh/harness-onboarding.md | 4 ++-- internal/harnessconfig/harness.go | 6 ++++++ internal/harnessconfig/mcode/declaration.go | 2 ++ .../internal/execution/harness_admission.go | 4 ++++ .../execution/harness_admission_test.go | 17 +++++++++++++++++ 8 files changed, 32 insertions(+), 7 deletions(-) diff --git a/apps/daemon/internal/agent/mcode/options.go b/apps/daemon/internal/agent/mcode/options.go index 703fdf0d7..8fb9e5fce 100644 --- a/apps/daemon/internal/agent/mcode/options.go +++ b/apps/daemon/internal/agent/mcode/options.go @@ -51,9 +51,6 @@ func prepareOptions(runtimeRoot string, req proto.PromptRequestPayload, workspac } opts := req.AgentOptions prompt := optionString(opts, "system_prompt") - if len(prompt) > 32*1024 { - return result, fmt.Errorf("mcode: combined instructions exceed the CLI's 32 KiB limit") - } if err := os.WriteFile(filepath.Join(result.DataDir, "AGENTS.md"), []byte(prompt), 0o600); err != nil { return result, err } diff --git a/apps/daemon/internal/agent/mcode/options_test.go b/apps/daemon/internal/agent/mcode/options_test.go index 989475c9b..027b5a961 100644 --- a/apps/daemon/internal/agent/mcode/options_test.go +++ b/apps/daemon/internal/agent/mcode/options_test.go @@ -67,7 +67,6 @@ func TestOptionsRejectDroppedContext(t *testing.T) { name string edit func(*proto.PromptRequestPayload) }{ - {"oversized instructions", func(r *proto.PromptRequestPayload) { r.AgentOptions["system_prompt"] = strings.Repeat("x", 32*1024+1) }}, {"missing model", func(r *proto.PromptRequestPayload) { delete(r.AgentOptions, "model") }}, {"missing provider", func(r *proto.PromptRequestPayload) { delete(r.AgentOptions, "model_provider") }}, } diff --git a/contracts/agents-api/harness-onboarding.md b/contracts/agents-api/harness-onboarding.md index e44277e89..695c28a4f 100644 --- a/contracts/agents-api/harness-onboarding.md +++ b/contracts/agents-api/harness-onboarding.md @@ -185,7 +185,7 @@ The declaration holds: - the public `Kind` and display `Label`; - the model `Configuration` ([native model configuration](#native-model-configuration)); - `Capabilities`, a `proto.AgentKindCapabilities` that states the most the Harness can do on a capable host, with every field `Supported` or `Unsupported` and the zero value invalid ([Capability declarations](../../docs/runtime-protocol.md#capability-declarations)); -- the supported `Placements` and public `MCPOrigins`, and whether whitespace-only text is accepted; +- the supported `Placements` and public `MCPOrigins`, whether whitespace-only text is accepted, and `MaxInstructionsBytes`, the native byte limit on an Agent's instructions (zero declares none), which admission rejects above; - `Execution`, the official execution option values the adapter maps to native settings: web search modes and whether search settings are accepted, reasoning efforts and summaries, service tiers, programmatic-tool-calling values and text verbosities. Core admission and the Runtime reject an undeclared value with the same check ([tool policy](./execution-tools.md#web-search-and-programmatic-tool-calling)). Core always sends the official default text verbosity, so `TextVerbosities` must include `medium`; - optional pure restrictions, `ValidateConfiguration`, `ValidateTools`, `ValidateMessageInput` and `ValidateFunctionResult`, that add native limits to the common checks. `ValidateMessageInput` runs only for messages that carry images, after the `MessageImages` capability check and before anything is stored, and decides which `image_url` values the Harness accepts; Core checks only that the reference is not blank. A nil validator means the common checks suffice. They cannot query business data, decrypt credentials or control native processes. Configuration restrictions run first, and a tool-decoding error precedes `ValidateTools`. diff --git a/contracts/agents-api/zh/harness-onboarding.md b/contracts/agents-api/zh/harness-onboarding.md index c2cab3c52..9df78c657 100644 --- a/contracts/agents-api/zh/harness-onboarding.md +++ b/contracts/agents-api/zh/harness-onboarding.md @@ -1,7 +1,7 @@ --- title: "Harness 协议" source: contracts/agents-api/harness-onboarding.md -source_hash: b3bd31e1272d7788db048b986cae774f4bc52902e91669ef7a87f86594014e18 +source_hash: 7fc635c711d04760883093996eb6415dde15c5cb42f3c5aed24f8f3cc20e87ab --- **Harness** 是一种运行模型和工具循环的原生代理引擎(Codex、Claude Code、MiniMax Code);**Harness 适配器**将 Runtime 的 Executor 和 Turn 契约转换到该引擎的 SDK 或协议。Harness 协议是 Runtime 与适配器之间的契约:适配器接口及其生命周期义务、声明、注册和验收。本文面向添加或维护 Harness 的开发者。 @@ -187,7 +187,7 @@ Runtime 统一解析[状态目录](../../../docs/zh/configuration.md#runtime-res - 公共 `Kind` 和显示用的 `Label`; - 模型 `Configuration`([原生模型配置](#native-model-configuration)); - `Capabilities`,即 `proto.AgentKindCapabilities`,表示 Harness 在能力完备的主机上最多能做什么;每个字段都是 `Supported` 或 `Unsupported`,零值无效([能力声明](../../../docs/zh/runtime-protocol.md#capability-declarations)); -- 受支持的 `Placements` 和公共 `MCPOrigins`,以及是否接受仅含空白的文本; +- 受支持的 `Placements` 和公共 `MCPOrigins`、是否接受仅含空白的文本,以及 `MaxInstructionsBytes`(原生对 Agent instructions 的字节上限,零表示没有上限,超出时准入会拒绝); - `Execution`,即适配器映射到原生设置的官方执行选项取值:web search 模式及是否接受搜索设置、推理强度和摘要、服务层级、程序化工具调用取值和文本详细程度。Core 准入和 Runtime 用同一检查拒绝未声明的取值([工具策略](execution-tools.md#web-search-and-programmatic-tool-calling))。Core 总会发送官方默认文本详细程度,因此 `TextVerbosities` 必须包含 `medium`; - 可选的纯限制 `ValidateConfiguration`、`ValidateTools`、`ValidateMessageInput` 和 `ValidateFunctionResult`,在通用检查之外添加原生限制。`ValidateMessageInput` 仅对携带图像的消息运行,在 `MessageImages` 能力检查之后、任何存储之前执行,决定 Harness 接受哪些 `image_url`;Core 只检查引用不为空白。验证函数为 nil 表示通用检查已足够。它们不能查询业务数据、解密凭据或控制原生进程。配置限制最先执行,工具解码错误先于 `ValidateTools`。 diff --git a/internal/harnessconfig/harness.go b/internal/harnessconfig/harness.go index 356020490..51838d690 100644 --- a/internal/harnessconfig/harness.go +++ b/internal/harnessconfig/harness.go @@ -97,6 +97,9 @@ type Declaration struct { // text. Unsupported Harnesses reject them at admission; Core never trims or // pads model input to fit a Harness. WhitespaceOnlyText proto.CapabilitySupport + // MaxInstructionsBytes is the native limit on an Agent's instructions in + // bytes; zero declares none. Admission rejects longer instructions. + MaxInstructionsBytes int // ValidateConfiguration adds pure restrictions on a saved Agent and // Environment. ValidateConfiguration func(Admission) error @@ -142,6 +145,9 @@ func (d Declaration) ValidateDeclaration() error { if d.WhitespaceOnlyText != proto.CapabilitySupported && d.WhitespaceOnlyText != proto.CapabilityUnsupported { return errors.New("harnessconfig: whitespace-only text support must be declared") } + if d.MaxInstructionsBytes < 0 { + return errors.New("harnessconfig: invalid instructions limit") + } if len(d.Placements) == 0 || !validChoices(d.Placements, "none", "openai_hosted", "self_hosted") { return errors.New("harnessconfig: invalid placements") } diff --git a/internal/harnessconfig/mcode/declaration.go b/internal/harnessconfig/mcode/declaration.go index e0f6330ac..b302695dd 100644 --- a/internal/harnessconfig/mcode/declaration.go +++ b/internal/harnessconfig/mcode/declaration.go @@ -67,6 +67,8 @@ var Declaration = harnessconfig.Declaration{ Placements: []string{"none", "openai_hosted", "self_hosted"}, MCPOrigins: []string{"service", "environment"}, WhitespaceOnlyText: proto.CapabilityUnsupported, + // Native MiniMax Code ignores global instructions (AGENTS.md) over 32 KiB. + MaxInstructionsBytes: 32 * 1024, ValidateTools: func(functions []proto.FunctionTool, mcp []proto.MCPHTTPServer) error { if err := harnessconfig.RequireObjectSchemas(functions); err != nil { return err diff --git a/services/core/internal/execution/harness_admission.go b/services/core/internal/execution/harness_admission.go index c4a4a995c..6065a82aa 100644 --- a/services/core/internal/execution/harness_admission.go +++ b/services/core/internal/execution/harness_admission.go @@ -3,6 +3,7 @@ package execution import ( "encoding/json" "errors" + "fmt" "github.com/MiniMax-AI/OpenAgentCore/internal/runtimebootstrap" "github.com/MiniMax-AI/OpenAgentCore/internal/agentdaemon/proto" @@ -40,6 +41,9 @@ func validateDeclaredConfiguration(declaration harnessconfig.Declaration, snapsh if snapshot.Agent.Text.Format.Type == "json_schema" && !declaration.Capabilities.StructuredOutput.IsSupported() { return errors.New("Structured output is not supported by this engine.") } + if limit := declaration.MaxInstructionsBytes; limit > 0 && snapshot.Agent.Instructions != nil && len(*snapshot.Agent.Instructions) > limit { + return fmt.Errorf("Instructions exceed this engine's limit of %d bytes.", limit) + } if declaration.ValidateConfiguration != nil { if err := declaration.ValidateConfiguration(admissionOf(snapshot)); err != nil { return admissionError(err) diff --git a/services/core/internal/execution/harness_admission_test.go b/services/core/internal/execution/harness_admission_test.go index 26264aea6..e3be4c12c 100644 --- a/services/core/internal/execution/harness_admission_test.go +++ b/services/core/internal/execution/harness_admission_test.go @@ -3,6 +3,7 @@ package execution import ( "encoding/json" "errors" + "strings" "testing" v1 "github.com/MiniMax-AI/OpenAgentCore/contracts/agents-api/v1" @@ -28,6 +29,22 @@ func TestAcceptedEnginePlacements(t *testing.T) { } } +func TestDeclaredInstructionsLimit(t *testing.T) { + session := func(engine string, size int) error { + raw := json.RawMessage(`{"agent":{"model":"fixture","instructions":"` + strings.Repeat("x", size) + `"},"environment":{"type":"none"}}`) + return (Policy{}).ValidateSessionConfiguration(engine, raw) + } + if err := session("mcode", 32*1024); err != nil { + t.Fatal("limit-sized instructions rejected", err) + } + if err := session("mcode", 32*1024+1); err == nil { + t.Fatal("instructions over the declared limit accepted") + } + if err := session("codex", 32*1024+1); err != nil { + t.Fatal("a Harness without a declared limit rejected instructions", err) + } +} + func TestAdditionalDeclarationUsesCommonAdmission(t *testing.T) { configurationChecked, toolsChecked, resultChecked := false, false, false declaration := harnesstest.Declaration("fixture", func(d *harnessconfig.Declaration) { From 501e979272ca35e45ad5b7833c69045a5582d9a5 Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:17:47 +0000 Subject: [PATCH 4/6] Record the official API native differences in the compatibility ledger --- contracts/agents-api/index.md | 5 +++++ contracts/agents-api/zh/index.md | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/contracts/agents-api/index.md b/contracts/agents-api/index.md index b33523076..260f76dd9 100644 --- a/contracts/agents-api/index.md +++ b/contracts/agents-api/index.md @@ -76,9 +76,11 @@ Each item is Core's deliberate or native behavior where the official service beh - Claude Code with live search on `environment: none` has only `WebSearch`, so search yields `search` actions and no page opens ([web search](./execution-tools.md#web-search-and-programmatic-tool-calling)). - An omitted reasoning effort stays null instead of taking the model's default. - Codex maps programmatic tool calling to its native `code_mode`, whose model-written scripts call the other tools; the feature is under development upstream. +- Codex rejects programmatic tool calling together with `multi_agent`. - A Session's `agent.tools` omits `tool_search` declarations. - Core rejects an inline `authorization` on a Session MCP transport, an `Authorization` entry in `headers` and a nonempty stdio `env`: credentials come only from Vaults (`credential_id`) and environment values only from the Environment (`env_vars`) ([MCP](./execution-tools.md#mcp)). - A `stdio` MCP server needs a workspace placement and the origin `environment`. Claude Code starts the server in its workspace directory, so `cwd` must equal it, with its whole process environment, which also holds the model provider key and other servers' Vault bearer tokens, and it needs `allowed_tools` null. MiniMax Code starts the server in its private home directory, so it rejects every `stdio` server ([MCP](./execution-tools.md#mcp)). +- Core rejects nonempty MCP `request_metadata`, a `stdio` server whose `connection_origin` is `service`, and a blank `server_label`, an empty `credential_id` and an empty `allowed_tools` name, which the pinned schema allows without defining their meaning (400 with the reason). - Claude rejects an MCP `server_url` or `headers` value containing `${`, because the native client expands `${VAR}` in both from a process environment that holds Core-held credentials. - Deleting a Session right after an events 202 returns 409, because Core admits the Turn in the same transaction; the official service returns 200. @@ -130,6 +132,8 @@ Each item is Core's deliberate or native behavior where the official service beh - A function result that cancellation prevents from being applied never appears as an Item. - Pinned Codex can lose command output emitted before its stream subscription. - Claude Code and MiniMax Code report no public usage. +- `agent_message` and `interrupt_subagent_call` Items are accepted by the Runtime protocol, but no Harness adapter produces them. +- Native file changes have no official Item type ([Turns and Items](./sessions-events.md#turns-and-items)). - MiniMax Code receives a message that starts with `/` with a trailing blank line, because ACP otherwise runs it as an operator command. - Core gives no crash-safe or exactly-once guarantee for native side effects; claimed work fails on restart without replay. - `file_id` and `detail` on images are rejected; each Harness declares which `image_url` values it accepts ([message content](./message-content.md#images)). @@ -145,6 +149,7 @@ Each item is Core's deliberate or native behavior where the official service beh **Files and Environment files** - Files accept only `purpose=user_data`; other purposes, `expires_after` and the Uploads API are not supported. +- The Skills create route accepts a single `files` part, but the pinned SDK sends no part when `files` is one file instead of a list ([upload a bundle](./source-files.md#upload-a-bundle)). - An Environment file write whose outcome is uncertain is never retried or recovered automatically; it blocks further writes and messages to the Session. **Vaults and Credentials** diff --git a/contracts/agents-api/zh/index.md b/contracts/agents-api/zh/index.md index b757d2d2c..320cf8fdc 100644 --- a/contracts/agents-api/zh/index.md +++ b/contracts/agents-api/zh/index.md @@ -1,7 +1,7 @@ --- title: "OpenAI 兼容性" source: contracts/agents-api/index.md -source_hash: 45ccd7e7fce53589dbf27fc82e75b59b61fffe5fc40a3bbbb8003a8dfd230cba +source_hash: afc5f4073341abbc15adb539ae44efd8c5d575d0e5ae2ec3028739cbf6538ea7 --- Core 实现下方固定版本的 OpenAI Agents API。本台账列出各项资源的覆盖情况、相对于官方服务的所有差异以及已知缺口。 @@ -79,9 +79,11 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh - Claude Code 在 `environment: none` 上启用 live 搜索时只有 `WebSearch`,因此搜索只产生 `search` 动作,不会打开页面([网页搜索](./execution-tools.md#web-search-and-programmatic-tool-calling))。 - 未指定推理强度时会保持为 null,而不是采用模型的默认值。 - Codex 把程序化工具调用映射到原生 `code_mode`,由模型编写的脚本调用其他工具;该功能在上游仍处于开发中。 +- Codex 拒绝同时使用程序化工具调用和 `multi_agent`。 - Session 的 `agent.tools` 会省略 `tool_search` 声明。 - Core 拒绝 Session MCP 传输中的内联 `authorization`、`headers` 中的 `Authorization` 条目以及非空的 stdio `env`:凭据只来自 Vault(`credential_id`),环境值只来自 Environment(`env_vars`)([MCP](execution-tools.md#mcp))。 - `stdio` MCP 服务器需要工作区部署位置和 `environment` 来源。Claude Code 在其工作区目录中启动服务器,因此 `cwd` 必须与之相同;服务器继承整个进程环境,其中也有模型提供方密钥和其他服务器的 Vault bearer 令牌;且 `allowed_tools` 须为 null。MiniMax Code 在其私有主目录中启动服务器,因此拒绝所有 `stdio` 服务器([MCP](execution-tools.md#mcp))。 +- Core 拒绝非空的 MCP `request_metadata`、`connection_origin` 为 `service` 的 `stdio` 服务器,以及空白的 `server_label`、空的 `credential_id` 和空的 `allowed_tools` 名称;固定版本的 schema 允许这些值但没有定义其含义(400,并说明原因)。 - Claude 会拒绝包含 `${` 的 MCP `server_url` 或 `headers` 值,因为原生客户端会从持有 Core 所持凭据的进程环境中展开这两处的 `${VAR}`。 - 在 events 202 之后立即删除 Session 会返回 409,因为 Core 会在同一事务中准入该 Turn;官方服务返回 200。 @@ -133,6 +135,8 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh - 如果取消导致函数结果无法应用,该结果将永远不会作为 Item 出现。 - 固定版本的 Codex 可能会丢失在订阅其流之前发出的命令输出。 - Claude Code 和 MiniMax Code 都不报告公共用量。 +- Runtime 协议接受 `agent_message` 和 `interrupt_subagent_call` Item,但没有 Harness 适配器会产生它们。 +- 原生文件变更没有对应的官方 Item 类型([Turns and Items](sessions-events.md#turns-and-items))。 - 以 `/` 开头的消息到达 MiniMax Code 时末尾多一个空行,否则 ACP 会将其作为操作员命令执行。 - 对于原生副作用,Core 不提供崩溃安全或恰好一次保证;已认领的工作若不重放,会在重启后失败。 - 图像上的 `file_id` 和 `detail` 会被拒绝;每个 Harness 声明自己接受哪些 `image_url`([消息内容](message-content.md#images))。 @@ -148,6 +152,7 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh **Files 和 Environment files** - Files 仅接受 `purpose=user_data`;不支持其他 `purpose` 值、`expires_after` 和 Uploads API。 +- Skills 创建路由接受单个 `files` 部分,但当 `files` 是单个文件而不是列表时,固定版本的 SDK 不会发送任何部分([上传 bundle](source-files.md#upload-a-bundle))。 - 结果不确定的 Environment file 写入不会自动重试或恢复;它会阻止后续写入以及向 Session 发送消息。 **Vaults 和 Credentials** From ab2283a0bf9b9f1d8a366c6a75327b984e0b0861 Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:21:16 +0000 Subject: [PATCH 5/6] Wrap the input batch comment --- services/core/internal/sessions/inputs.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/internal/sessions/inputs.go b/services/core/internal/sessions/inputs.go index b8f730883..48aae4155 100644 --- a/services/core/internal/sessions/inputs.go +++ b/services/core/internal/sessions/inputs.go @@ -42,8 +42,8 @@ func ValidateInputKey(key string) error { // ValidateInputs checks and normalizes an input batch: 1..16384 messages (the // official events bound), cancellations and function results whose nonempty // JSON object payloads total at most 2 MiB, which fits 16384 minimal messages, -// an empty cancellation payload and a well-formed function result. It returns the normalized batch and its encoding, the batch's retry -// identity. +// an empty cancellation payload and a well-formed function result. It returns +// the normalized batch and its encoding, the batch's retry identity. func ValidateInputs(inputs []Input) ([]Input, json.RawMessage, error) { if len(inputs) == 0 || len(inputs) > 16384 { return nil, nil, fmt.Errorf("%w: input batch must contain 1..16384 events", ErrInvalidInput) From c0aaf5f48d2003d57b9e723ae50896c35abbbfc7 Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Sat, 24 Oct 2026 02:46:50 +0000 Subject: [PATCH 6/6] Refresh the compatibility translation hash --- contracts/agents-api/zh/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/agents-api/zh/index.md b/contracts/agents-api/zh/index.md index 320cf8fdc..24f7e3d51 100644 --- a/contracts/agents-api/zh/index.md +++ b/contracts/agents-api/zh/index.md @@ -1,7 +1,7 @@ --- title: "OpenAI 兼容性" source: contracts/agents-api/index.md -source_hash: afc5f4073341abbc15adb539ae44efd8c5d575d0e5ae2ec3028739cbf6538ea7 +source_hash: 4bccb4aaa93b5773708c46915447791443532cc3d0a9705124ee9e5812c5bf05 --- Core 实现下方固定版本的 OpenAI Agents API。本台账列出各项资源的覆盖情况、相对于官方服务的所有差异以及已知缺口。