diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 193c6a910..c5c17cff8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -3594,6 +3594,18 @@ The [package artifact contract](packages/claude-sdk-adapter/README.md#runtime-ar
owns build isolation, dependency export, readiness and relocation checks.
Keep the adapter artifact independent of the Core binary and product sources.
+### Harness model configuration
+
+The configuration preparation contract in `apps/parsar-daemon/internal/agent/harness.go`
+is mandatory for every Executor factory. Shared wire types live in
+`internal/agentdaemon/proto`; native model fields and their application are documented
+in [Harness onboarding](contracts/agents-api/harness-onboarding.md#native-model-configuration).
+The standalone Core build includes the shared `internal/modeltransport` route
+qualification code alongside the adapter declarations; Runtime still owns proxy
+startup and request forwarding.
+Public configuration sources and inheritance belong to
+[model execution](contracts/agents-api/model-execution.md).
+
### Harness selection and Agent defaults
Core accepts the optional `agent.x_agents_core.harness` extension through the
diff --git a/apps/docs/content/docs/admin-api.mdx b/apps/docs/content/docs/admin-api.mdx
index 001a2b8c0..a88731588 100644
--- a/apps/docs/content/docs/admin-api.mdx
+++ b/apps/docs/content/docs/admin-api.mdx
@@ -8,7 +8,7 @@ resource inspection, Project and key management, credential issuance, audit, usa
and sandbox operations. It never calls `/v1` or `/api/v1`, and has no Agent
execution, copy or arbitrary asset editing operation.
-Core request failures use the [Core administration error envelope](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core-errors.md),
+Core request failures use the [Core administration error envelope](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-errors.md),
including optional typed safe details. Console sign-in endpoints retain their
separate error shape described below.
@@ -49,9 +49,9 @@ label, but could set any value. Never use it for authorization or as proof of
origin.
Web calls Core only through the typed Core clients in `packages/agents-client`:
-[AdminClient](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/packages/agents-client/src/admin-client.ts) (`/core/v1`),
+[AdminClient](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/packages/agents-client/src/admin-client.ts) (`/core/v1`),
`SandboxAdminClient` (`/core/v1/sandbox`) and `CoreMetricsClient`
-(`/core/v1/metrics`). See [the complete administrator reference](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md)
+(`/core/v1/metrics`). See [the complete administrator reference](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md)
for methods, fields, filters, pagination and response shapes.
Routes below are relative to `/core/v1`:
@@ -62,8 +62,8 @@ Routes below are relative to `/core/v1`:
| Resource lists/details/deletion | `/projects/{id}/agents`, `/sessions`, `/environment-templates`, `/skills`, `/files`, `/vaults`, including the documented nested reads |
| Asset ownership | `GET /projects/{id}/resource-owners` with batched resource IDs |
| Key operation history | `GET /projects/{id}/write-operations` with key/resource/time filters |
-| Executor credentials | `GET/POST /projects/{id}/environments/{environment_id}/executor-credentials`, `DELETE …/executor-credentials/{key_id}` ([contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md)) |
-| Deployment model providers | `GET /harnesses`, `GET/PUT/DELETE /harnesses/{harness}/model-provider`; the key is write-only ([contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md#deployment-defaults)) |
+| Executor credentials | `GET/POST /projects/{id}/environments/{environment_id}/executor-credentials`, `DELETE …/executor-credentials/{key_id}` ([contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md)) |
+| Deployment model configuration | `GET /harnesses`, `GET/PUT/DELETE /harnesses/{harness}/model-configuration`; the key is write-only ([contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md#deployment-defaults)) |
| Usage and health | `GET /summary`, `/sandbox/runtime-observations`, `/metrics` |
| Administrator audit | `GET /audit-log`; deployment-wide entries have `project_id: null` |
@@ -76,9 +76,9 @@ it is operational attribution, not per-key billing.
## Sandbox administration
-The [deployment configuration contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/sandbox-deployment.md),
-[nodes and sandbox backends reference](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md)
-and [generated OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core.openapi.yaml)
+The [deployment configuration contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/sandbox-deployment.md),
+[nodes and sandbox backends reference](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md)
+and [generated OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core.openapi.yaml)
define deployment and node operations:
- `GET/POST/PUT /core/v1/sandbox/deployment` and
@@ -115,7 +115,7 @@ is a durable serving pin, not proof of current connectivity. Target unknown, fai
or update-required state does not by itself invalidate confirmed old-generation
service; consume Core's connection/provider facts separately.
-Administrators may [archive an individual hosted Session](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md#administrative-session-archive)
+Administrators may [archive an individual hosted Session](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md#administrative-session-archive)
at the current generation without reset. History and persisted Files/Artifacts
survive; unpersisted workspace is lost and the original Session cannot resume.
Cancel reset stops further archives, not cleanup already requested. After zero
@@ -156,7 +156,7 @@ generated schema; do not interpret every empty or failed read as an absent resou
`GET /core/v1/metrics?range=1h|6h|24h|7d` returns Core process, execution
queue/slots, PostgreSQL and background-job measurements. It requires the Core key,
rejects arbitrary query filters and never grants
-Agent execution access. See the [exact measurement contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core-metrics.md)
+Agent execution access. See the [exact measurement contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-metrics.md)
for complete buckets, null values, units and process-local retention. Frontend
implementation is maintained separately; this backend change does not modify
Agent metrics or the public Agent API.
@@ -165,7 +165,7 @@ Agent metrics or the public Agent API.
The Core key reads a node and its host history through
`GET /core/v1/sandbox/nodes/{node_id}?range=1h|6h|24h`. See the
-[node host history contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/node-host-history.md)
+[node host history contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/node-host-history.md)
for nullable observations, freshness and aggregation. The node list is unchanged.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/api/web-management.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/api/web-management.md)
diff --git a/apps/docs/content/docs/agents-and-tools.mdx b/apps/docs/content/docs/agents-and-tools.mdx
index bebf10794..787ae1ae4 100644
--- a/apps/docs/content/docs/agents-and-tools.mdx
+++ b/apps/docs/content/docs/agents-and-tools.mdx
@@ -4,7 +4,7 @@ description: "Native harness tools, shared declarations and the limits of execut
---
Assessed against Core `206474a4c10901442b1faa094281bfb5559082b5` on 2026-09-22.
-The contract remains [OpenAI Python 3.13.0 at `d7c41ef`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream.json), Beta
+The contract remains [OpenAI Python 3.13.0 at `d7c41ef`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream.json), Beta
`agents=v1`. This matrix records the bounded execution/tools milestone. It does not
establish complete protocol compatibility; the remaining limits below stay open.
@@ -22,20 +22,20 @@ and Environment Plugin MCP have separate inventories and qualification.
| Operation | Implemented behavior and real qualification | Unsupported or unverified boundary |
| --- | --- | --- |
-| Initial message input, `sessions.create` | String input and ordered user-message arrays share atomic admission. Codex/Claude text and inline image execution: M1/M2; ordinary MiniMax text: M1/P1. [Input contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/message-input.md), [initial parser](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/session_initial_input.go). | Whitespace-only text is admitted verbatim for Codex and rejected at admission for Claude SDK and MiniMax Code ([text content](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/message-input.md#text-content)). Empty parts beside text (SES-08) and local size-limit parity need upstream evidence. Images are only qualified for inline PNG/JPEG on `none` and Core-managed Docker `openai_hosted`; MiniMax, self-hosted images and remote URLs remain gaps. |
-| Prepared and active messages, `sessions.events.create` | Ordered `input_text`/`input_image` arrays retain original content and distinct public user Items. HTTP 202 confirms persistence; native receipts establish application. Initial/prepared/active Docker PNG/JPEG: M2; active PNG on `none`: M1. [Shared admission](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/inputs.go). | Codex flattens native messages with blank-line separators. Claude can fold or queue native turns; it does not promise Codex's same-native-turn behavior. Public durability does not prove native consumption. Claude SDK and MiniMax Code reject messages without an image or non-whitespace text at admission (`unsupported_or_invalid_configuration`); Codex delivers them unchanged. |
-| Structured output, `agent.text.format` | Save/inherit/freeze `{type:json_schema,schema:...}`. Claude SDK object-root, single Agent, medium verbosity, ordinary functions returning text: S1 (`none`) and S2 (Docker, including prepared/active input and Files/Artifacts). Native final text is retained unchanged; its stream follows the official message sequence with the whole text in one `output_text.delta` ([item serialization](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/history-events-usage.md#item-serialization-2026-09-23)). [Contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/structured-output.md), [profile](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/engine/claude.go). | An explicit non-object root type is a protocol error for every harness ([validation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/official-semantics-alignment.md#agent-configuration-validation--september-23)). Codex/MiniMax, schemas without an object root, schema numbers changed by binary64, self-hosted, Skills/Plugins, MCP, Subagent and discovery combinations reject execution. No output repair, coercion or extra model loop. Arbitrary schema dialects are unverified. |
-| Function configuration, saved/inline Agents | Required name/description/schema; `defer_loading` defaults false. Protocol errors, repeated names and explicit non-object root types reject with the official fields ([validation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/official-semantics-alignment.md#agent-configuration-validation--september-23)). Saved references resolve into an immutable Session snapshot. Codex/Claude real calls: F1/F2/M2/S1/S2. [Parser](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/function_configuration.go), [saved tools](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/saved_tools.go). | MiniMax public functions reject. Claude requires an explicit object root. Local nonblank/512-byte name and 64-definition Session bounds are compatibility gaps. Saving configuration alone does not qualify execution. |
-| Function-result admission, `events.create` | Required `turn_id`, `call_id`, `success`; optional nullable `error` and `output`. Output is string or ordered text/image content. Scoped atomic batches retain field presence, original content and retry identity in storage; public result Items and events always carry `output` and `error`, null when not submitted ([item serialization](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/history-events-usage.md#item-serialization-2026-09-23)). Same result retries are accepted; changed results and results after cancellation return 409 `conflict_error`, including after terminal state. In the caller's Session, an unknown call or a call of another Turn returns 400 `invalid_request_error` without changing the pending action; missing and foreign Sessions stay 404 ([error rows](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/official-semantics-alignment.md#session-input-conflicts-and-result-targets--september-23)). F1/F2/M2 plus [controlled SDK/raw checks](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/tests/official_function_inputs.py). [Parser](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/function_inputs.go), [Store](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/function_inputs.go). | Admission is separate from application and public Item publication. Invalid or unqualified content cannot consume a pending call. Core messages omit the call and executor IDs that official messages name; hosted defaults and publication timing remain unverified. |
-| Function text results and native application | Codex waits for a matching live root dynamic-tool completion; Claude waits for a matching live root native tool result. Text/error results, retry/conflict, cancellation and cold continuation: F1/F2. [Receipt contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/function-result-images.md). | Transport writes alone do not confirm application. Confirmation is not provider consumption, crash recovery or exactly-once external effects. No automatic result replay. |
+| Initial message input, `sessions.create` | String input and ordered user-message arrays share atomic admission. Codex/Claude text and inline image execution: M1/M2; ordinary MiniMax text: M1/P1. [Input contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md), [initial parser](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/session_initial_input.go). | Whitespace-only text is admitted verbatim for Codex and rejected at admission for Claude SDK and MiniMax Code ([text content](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md#text-content)). Empty parts beside text (SES-08) and local size-limit parity need upstream evidence. Images are only qualified for inline PNG/JPEG on `none` and Core-managed Docker `openai_hosted`; MiniMax, self-hosted images and remote URLs remain gaps. |
+| Prepared and active messages, `sessions.events.create` | Ordered `input_text`/`input_image` arrays retain original content and distinct public user Items. HTTP 202 confirms persistence; native receipts establish application. Initial/prepared/active Docker PNG/JPEG: M2; active PNG on `none`: M1. [Shared admission](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/inputs.go). | Codex flattens native messages with blank-line separators. Claude can fold or queue native turns; it does not promise Codex's same-native-turn behavior. Public durability does not prove native consumption. Claude SDK and MiniMax Code reject messages without an image or non-whitespace text at admission (`unsupported_or_invalid_configuration`); Codex delivers them unchanged. |
+| Structured output, `agent.text.format` | Save/inherit/freeze `{type:json_schema,schema:...}`. Claude SDK object-root, single Agent, medium verbosity, ordinary functions returning text: S1 (`none`) and S2 (Docker, including prepared/active input and Files/Artifacts). Native final text is retained unchanged; its stream follows the official message sequence with the whole text in one `output_text.delta` ([item serialization](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/history-events-usage.md#item-serialization-2026-09-23)). [Contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/structured-output.md), [profile](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/engine/claude.go). | An explicit non-object root type is a protocol error for every harness ([validation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/official-semantics-alignment.md#agent-configuration-validation--september-23)). Codex/MiniMax, schemas without an object root, schema numbers changed by binary64, self-hosted, Skills/Plugins, MCP, Subagent and discovery combinations reject execution. No output repair, coercion or extra model loop. Arbitrary schema dialects are unverified. |
+| Function configuration, saved/inline Agents | Required name/description/schema; `defer_loading` defaults false. Protocol errors, repeated names and explicit non-object root types reject with the official fields ([validation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/official-semantics-alignment.md#agent-configuration-validation--september-23)). Saved references resolve into an immutable Session snapshot. Codex/Claude real calls: F1/F2/M2/S1/S2. [Parser](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/function_configuration.go), [saved tools](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/saved_tools.go). | MiniMax public functions reject. Claude requires an explicit object root. Local nonblank/512-byte name and 64-definition Session bounds are compatibility gaps. Saving configuration alone does not qualify execution. |
+| Function-result admission, `events.create` | Required `turn_id`, `call_id`, `success`; optional nullable `error` and `output`. Output is string or ordered text/image content. Scoped atomic batches retain field presence, original content and retry identity in storage; public result Items and events always carry `output` and `error`, null when not submitted ([item serialization](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/history-events-usage.md#item-serialization-2026-09-23)). Same result retries are accepted; changed results and results after cancellation return 409 `conflict_error`, including after terminal state. In the caller's Session, an unknown call or a call of another Turn returns 400 `invalid_request_error` without changing the pending action; missing and foreign Sessions stay 404 ([error rows](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/official-semantics-alignment.md#session-input-conflicts-and-result-targets--september-23)). F1/F2/M2 plus [controlled SDK/raw checks](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/tests/official_function_inputs.py). [Parser](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/function_inputs.go), [Store](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/function_inputs.go). | Admission is separate from application and public Item publication. Invalid or unqualified content cannot consume a pending call. Core messages omit the call and executor IDs that official messages name; hosted defaults and publication timing remain unverified. |
+| Function text results and native application | Codex waits for a matching live root dynamic-tool completion; Claude waits for a matching live root native tool result. Text/error results, retry/conflict, cancellation and cold continuation: F1/F2. [Receipt contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/function-result-images.md). | Transport writes alone do not confirm application. Confirmation is not provider consumption, crash recovery or exactly-once external effects. No automatic result replay. |
| Function image results | Successful ordered inline PNG/JPEG with text, large PNG and image-only JPEG: Codex/Claude `none` F1/F2; Docker M2. Public Items retain submitted bytes. Codex receipt regression: F2. | Claude rejects failed images and remote references before persistence; native resizing may change its image bytes. MiniMax functions and self-hosted image workflows are unqualified. Other Codex image/error/reference combinations cannot be inferred from successful-inline evidence. |
-| Deferred function discovery | Type-only `tool_search` plus mixed eager/deferred functions: Claude SDK 0.3.269/native 2.1.269, Kimi K3, single Agent, medium, `none`, text results; text and PNG input D1. Native provider observations establish lazy schema loading. [Contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/tool-search.md). | A repeated `tool_search` is a protocol error. Codex/MiniMax discovery, search-only/missing-search, workspace, MCP, structured-output and Subagent combinations remain gaps. Opaque native policy changes lack a reliable pre-input deferral signal. Saved tools include `tool_search`; the pinned Session response union excludes it. Exact hosted projection is unverified. |
-| Explicit disabled search/PTC | Saved and inline `web_search.mode=disabled` and `programmatic_tool_calling.enabled=false`; shared native controls on initial and cold execution. All three harnesses on `none`: P1, including native inventory/control evidence. [Contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/tool-policy.md), [parser](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/api/disabled_tools.go). | Unsupported explicit enablement rejects at Session admission; saved Agents keep every pinned search mode as resource data (TV-05), and Sessions from such Agents reject unless they replace the tools. A repeated `web_search` is a protocol error. Omission retains approved native behavior, which does not establish official default-on PTC parity. Enabled search and default/error parity remain gaps; unrelated native utilities are not implicitly removed. |
-| Agent service-origin MCP | Implemented Codex/Claude HTTP `none` profiles, anonymous/static bearer, scoped Vault selection and native `mcp_call` Items. [Configuration and qualification limits](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/README.md#http-mcp-execution), [profiles](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/engine/profile.go). | This closure batch does not requalify MCP/provider combinations. MiniMax, self-hosted/hosted service-origin MCP, OAuth, nonempty inline headers/metadata and other transports/origins reject. Claude requires a static connected inventory; original MCP-envelope fidelity and continuing server health are unverified. |
-| Environment Plugin MCP/native tools | Separate [Docker Plugin transport matrix](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-templates.md#environment-origin-mcp-plugins) and [V1 deployment evidence](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/user-managed-runtime-v1.md). Native tools stay within the existing colocated Runtime. | Plugin MCP is not Agent service-origin MCP or a public function action. No new optional cross-product is qualified here. Native utility inventories need not be identical. |
-| Required action: `function_call` | Session GET/list and Session SSE expose persisted `{arguments,call_id,name,turn_id,type}`. Actions remain pending until native application or cancellation/terminal settlement. [Projection](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/function_state.go), [confirmation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/function_results.go); real handling F1/F2/M2/S1/S2/D1; explicit client disconnect/query/reconnect: F3. | Function-call history is not pending-state authority. Client reconnect does not replay events or redo external application effects. |
-| Required action: `environment_connection` | Offline waiting input exposes `{environment_id,type}` before Turn creation. Connect the exact Session Environment through our scoped daemon enrollment. Three-harness Docker/E2B execution: E1; explicit initial pending-input/query/connection/native completion: E2; expiry: [controlled initial-input test](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/tests/official_self_hosted_initial.py). | Idle offline Sessions without pending input request nothing. Registration alone is not connectivity or native readiness. Stock `exec-server`/Noise transport is outside the approved V1 route. Exact upstream registration/action-removal timing remains unverified. |
-| Stream disconnect and execution loss | SSE is live-only. Reconnect, buffer events, retrieve Session/Turn/Items and deduplicate Item IDs. Worker recovery fails previously claimed work without replay; queued work can remain. [Recovery contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md#public-execution-admission), [connection reconciliation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/environment_connection_recovery.go). | Client disconnect and daemon/Core loss are different cases. F3 qualifies client-stream loss and continued pending function handling; F2 qualifies native process loss with an unapplied saved result. Neither promises replay or recovery of unknown external effects. |
+| Deferred function discovery | Type-only `tool_search` plus mixed eager/deferred functions: Claude SDK 0.3.269/native 2.1.269, Kimi K3, single Agent, medium, `none`, text results; text and PNG input D1. Native provider observations establish lazy schema loading. [Contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/tool-search.md). | A repeated `tool_search` is a protocol error. Codex/MiniMax discovery, search-only/missing-search, workspace, MCP, structured-output and Subagent combinations remain gaps. Opaque native policy changes lack a reliable pre-input deferral signal. Saved tools include `tool_search`; the pinned Session response union excludes it. Exact hosted projection is unverified. |
+| Explicit disabled search/PTC | Saved and inline `web_search.mode=disabled` and `programmatic_tool_calling.enabled=false`; shared native controls on initial and cold execution. All three harnesses on `none`: P1, including native inventory/control evidence. [Contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/tool-policy.md), [parser](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/api/disabled_tools.go). | Unsupported explicit enablement rejects at Session admission; saved Agents keep every pinned search mode as resource data (TV-05), and Sessions from such Agents reject unless they replace the tools. A repeated `web_search` is a protocol error. Omission retains approved native behavior, which does not establish official default-on PTC parity. Enabled search and default/error parity remain gaps; unrelated native utilities are not implicitly removed. |
+| Agent service-origin MCP | Implemented Codex/Claude HTTP `none` profiles, anonymous/static bearer, scoped Vault selection and native `mcp_call` Items. [Configuration and qualification limits](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/README.md#http-mcp-execution), [profiles](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/engine/profile.go). | This closure batch does not requalify MCP/provider combinations. MiniMax, self-hosted/hosted service-origin MCP, OAuth, nonempty inline headers/metadata and other transports/origins reject. Claude requires a static connected inventory; original MCP-envelope fidelity and continuing server health are unverified. |
+| Environment Plugin MCP/native tools | Separate [Docker Plugin transport matrix](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md#environment-origin-mcp-plugins) and [V1 deployment evidence](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/user-managed-runtime-v1.md). Native tools stay within the existing colocated Runtime. | Plugin MCP is not Agent service-origin MCP or a public function action. No new optional cross-product is qualified here. Native utility inventories need not be identical. |
+| Required action: `function_call` | Session GET/list and Session SSE expose persisted `{arguments,call_id,name,turn_id,type}`. Actions remain pending until native application or cancellation/terminal settlement. [Projection](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/function_state.go), [confirmation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/function_results.go); real handling F1/F2/M2/S1/S2/D1; explicit client disconnect/query/reconnect: F3. | Function-call history is not pending-state authority. Client reconnect does not replay events or redo external application effects. |
+| Required action: `environment_connection` | Offline waiting input exposes `{environment_id,type}` before Turn creation. Connect the exact Session Environment through our scoped daemon enrollment. Three-harness Docker/E2B execution: E1; explicit initial pending-input/query/connection/native completion: E2; expiry: [controlled initial-input test](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/tests/official_self_hosted_initial.py). | Idle offline Sessions without pending input request nothing. Registration alone is not connectivity or native readiness. Stock `exec-server`/Noise transport is outside the approved V1 route. Exact upstream registration/action-removal timing remains unverified. |
+| Stream disconnect and execution loss | SSE is live-only. Reconnect, buffer events, retrieve Session/Turn/Items and deduplicate Item IDs. Worker recovery fails previously claimed work without replay; queued work can remain. [Recovery contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md#public-execution-admission), [connection reconciliation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/environment_connection_recovery.go). | Client disconnect and daemon/Core loss are different cases. F3 qualifies client-stream loss and continued pending function handling; F2 qualifies native process loss with an unapplied saved result. Neither promises replay or recovery of unknown external effects. |
## Required-action recovery contract
@@ -52,7 +52,7 @@ application already performed the function, keep and submit that saved result;
do not run an external effect again merely because an action remains visible.
Core's acknowledgement boundary is native application. For an environment action,
connect its exact Environment using the existing enrollment authorization.
-[Connection observations](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/environment_connections.go)
+[Connection observations](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/environment_connections.go)
fence stale generations; transport connection can clear pre-Turn activity before
native preparation. Neither registration nor an action disappearing proves that
a model ran successfully. Query the matching Turn and Items for its outcome.
@@ -61,8 +61,8 @@ Two timing questions remain open. Repeated `requires_action` notification order
and acknowledgement timing are local implementation choices, not proven upstream
semantics. Also, an admitted result that is cancelled before native observation
can remain internally saved without a public output Item or `item.added`.
-[Item publication](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/store/item_projection.go) and
-[the existing coverage record](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md#public-function-configuration) preserve
+[Item publication](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/store/item_projection.go) and
+[the existing coverage record](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md#public-function-configuration) preserve
this gap. Successful retry cannot manufacture the missing observation or establish
that the model consumed the result.
@@ -82,12 +82,12 @@ not a claim that every historical workflow was rerun at the current baseline.
| M2 | `20260922/workspace-images/validation-summary.json`; Codex `public-run-_lr5uiy_`, Claude `public-run-sb65p9e9`; candidate `2c295116d66ed9aafc808ec49a8cb6dcb5c674c2`, merge `1adb2489bc3415039440224e9a7905c53e68a557` ([#17](https://github.com/MiniMax-AI/parsar-core/pull/17)). Kimi K3, Codex 0.153.4, Claude SDK 0.3.269/native 2.1.269; Docker seven-Turn image/workspace workflow. Codex's receipt conclusion is superseded by F2. |
| F1 | `20260922/function-result-images/validation-summary.json`, `validated/function-image-public-2567456666/public.json`; candidate `d3cdb225bc7628b968b76c7e1b400101894ce8cd`, merge `fd23f169e1ede1b2f1c39a1d9dcce71886e3c006` ([#16](https://github.com/MiniMax-AI/parsar-core/pull/16)). Claude SDK 0.3.269/native 2.1.269 with Kimi K3 on `none`; success PNG/JPEG, failed text, retries, cancellation, history continuation. Earlier Codex transport-only evidence does not qualify current receipts. |
| F2 | `20260922/function-result-receipts/validation-summary.json`, `candidate-public-owner-sdk.log`; hosted `public-run-4fn70foy` (104.13s), `none` `function-image-public-945075091` (83.918s). Candidate `6dceb98e1c56469fcc70cd82025ce77fc870ed3d`, merge `206474a4c10901442b1faa094281bfb5559082b5` ([#20](https://github.com/MiniMax-AI/parsar-core/pull/20)); real Kimi, Codex 0.153.4. Qualifies native receipts, not completed provider consumption. |
-| F3 | `20260922/execution-tools-closure/pending-actions/validation-summary.json`; Codex `codex/public-run-8gexf5a8` (65.58s), Claude `claude_sdk/public-run-5f2tr7e_` (74.33s), production source `206474a`. The same [public verifier](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/tests/official_pending_actions_native.py) checks disconnected-client pending queries, success/error/cancel, original results, target isolation, retry/conflict and no implicit call replay with real Kimi on Docker. No Core restart or native-loss injection is claimed by these runs. |
+| F3 | `20260922/execution-tools-closure/pending-actions/validation-summary.json`; Codex `codex/public-run-8gexf5a8` (65.58s), Claude `claude_sdk/public-run-5f2tr7e_` (74.33s), production source `206474a`. The same [public verifier](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/tests/official_pending_actions_native.py) checks disconnected-client pending queries, success/error/cancel, original results, target isolation, retry/conflict and no implicit call replay with real Kimi on Docker. No Core restart or native-loss injection is claimed by these runs. |
| S1 | `20260922/structured-output/acceptance-summary.json`, `structured-public-1905281777/public.json`; real candidate `7f533d46c472f3cdf7c16ce9471c225a2ba7eded`, merge `8716e699dbc34904499c94b6b0b03857bbebfaad` ([#11](https://github.com/MiniMax-AI/parsar-core/pull/11)). Claude/Kimi `none` schema/function execution and cold continuation. Schema-specific active steering was not separately qualified here. |
| S2 | `20260922/hosted-structured-output/validation-summary.json`, `validated/public-inline.log`, `public-run-qvq3csf1` (186.09s); candidate `f6d2c3f2a1dc2ff5f177213bd2b20d78496011d0`, merge `aa85d8ecc60e0a8b7f2494b73caa81216ee197e2` ([#18](https://github.com/MiniMax-AI/parsar-core/pull/18)). Claude SDK 0.3.269/native 2.1.269, real Kimi; Docker saved/inline schema, prepared/active input, native files and four completed structured answers. |
| D1 | `20260922/deferred-tools/tool-search-public-2039155387/public.json`, `public-image-isolated-tests.log` (86.71s); merge `178507ae7a63d4068e1e82bef9cd256ba398ae00` ([#13](https://github.com/MiniMax-AI/parsar-core/pull/13)). Claude SDK 0.3.269/native 2.1.269/Kimi K3 `none`; text results with initial/active PNGs, cancellation and cold continuation. `claude-native-1790052750` separately records provider schema inventories and native feasibility. |
| P1 | `20260922/tool-policy/acceptance.json`, `server-evidence/tool-policy-{codex-2495445746,claude_sdk-2539346823,mcode-3747575401}/public.json`; candidate `eeb432c7495265ae3a9309e32f5b4323611c3245`, merge `4b8754a6eda6696d9b18eb8d583953ac16c6800f` ([#14](https://github.com/MiniMax-AI/parsar-core/pull/14)). Codex/Claude Kimi K3, MiniMax M2.7; four `none` Sessions per harness, native disable controls and cold continuation. |
-| E1 | `20260921/self-hosted-onboarding/{source-candidate.json,source-verified.json,live,live-e2b}`; candidate `8f0cd2530d7b58cb7fb3ea124a1fc43dacecca36`. [Exact Docker/E2B run paths and limits](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/user-managed-runtime-v1.md#evidence-and-verification-boundaries): Codex Kimi K3 Responses, Claude Kimi K3 Anthropic-compatible API, MiniMax M2.7, immutable Linux amd64 Runtime builds. Native execution, restart/history, cancellation, Files/Artifacts and isolation; shared credential lifecycle evidence is not a separate live rotation run for every E2B profile. |
+| E1 | `20260921/self-hosted-onboarding/{source-candidate.json,source-verified.json,live,live-e2b}`; candidate `8f0cd2530d7b58cb7fb3ea124a1fc43dacecca36`. [Exact Docker/E2B run paths and limits](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/user-managed-runtime-v1.md#evidence-and-verification-boundaries): Codex Kimi K3 Responses, Claude Kimi K3 Anthropic-compatible API, MiniMax M2.7, immutable Linux amd64 Runtime builds. Native execution, restart/history, cancellation, Files/Artifacts and isolation; shared credential lifecycle evidence is not a separate live rotation run for every E2B profile. |
| E2 | `20260922/execution-tools-closure/environment-actions/result.json` contains Codex/Claude Kimi passes (13 checks each) and the retained MiniMax direct-network failure; `mcode-relay-retry/result.json` separately passes MiniMax M2.7 (13 checks) after correcting provider routing. Source `206474a`; same shared SDK/raw workflow, isolated Core/PostgreSQL and user-managed Docker. Covers initial creation SSE, client disconnect, exact pending Environment/no Turn or Items, scoped enrollment, one actual completed model Turn and creation retries preserving history. This is connection-action qualification, not another full lifecycle or E2B regression. |
Controlled tests establish parser, projection, atomicity and race behavior; native
@@ -121,4 +121,4 @@ remain separate limitations. They do not authorize silently relabeling an unprov
principal workflow as deferred. OAuth, full Usage, release publication, new tool
kinds and new execution loops are outside this closure batch.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/execution-tools.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/execution-tools.md)
diff --git a/apps/docs/content/docs/api-reference/core/deployment-model-providers.mdx b/apps/docs/content/docs/api-reference/core/deployment-model-providers.mdx
index 5f8541157..abffbdde1 100644
--- a/apps/docs/content/docs/api-reference/core/deployment-model-providers.mdx
+++ b/apps/docs/content/docs/api-reference/core/deployment-model-providers.mdx
@@ -13,9 +13,10 @@ _openapi:
- content: >-
Core key only. Returns every harness this build supports, in name
order. enabled and default are read-only views of the process
- configuration (OAC_DEFAULT_HARNESS and OAC_HARNESSES). model_provider
- is the harness's deployment default, stored in Core, or null. Keys are
- never returned; api_key_configured reports that one is set.
+ configuration (OAC_DEFAULT_HARNESS and OAC_HARNESSES).
+ model_configuration is the harness's deployment default, stored in
+ Core, or null. Keys are never returned; api_key_configured reports
+ that one is set.
- content: >-
Core key only. Returns the safe view; the key is never returned. 404
when the harness does not exist or has no deployment default. Nullable
@@ -29,21 +30,22 @@ _openapi:
openai_hosted Sessions for this harness need a Session or Agent
bundle.
- content: >-
- Core key only. The body is the complete x_agents_core.model_provider
- bundle, including the write-only api_key; there is no partial update
- and bundles are never merged. The provider is validated for this
- harness: an HTTPS base_url without credentials, query or fragment, an
- upstream protocol (responses, anthropic or chat_completions),
- automatically adapted by Runtime to the selected harness and, for
- mcode, positive context_window and max_output_tokens. New
- openai_hosted and none Sessions that resolve no Session or Agent
- bundle freeze this default into their encrypted snapshot; existing
- Sessions never change. self_hosted Sessions never use it. The key is
- encrypted and never returned. Each write records an administrator
- audit entry without the key and resets last_used_at, last_error_code
- and last_error_at to null, including identical writes.
+ Core key only. The body is the complete
+ x_agents_core.model_configuration bundle, including the write-only
+ api_key; there is no partial update and bundles are never merged. The
+ provider is validated for this harness: an HTTPS base_url without
+ credentials, query or fragment, an upstream protocol (responses,
+ anthropic or chat_completions), automatically adapted by Runtime to
+ the selected harness and, for mcode, positive context_window and
+ max_output_tokens. New openai_hosted and none Sessions resolve omitted
+ model settings from this default and freeze the resolved configuration
+ into their encrypted snapshot; existing Sessions never change.
+ self_hosted Sessions never use it. The key is encrypted and never
+ returned. Each write records an administrator audit entry without the
+ key and resets last_used_at, last_error_code and last_error_at to
+ null, including identical writes.
---
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/apps/docs/content/docs/bootstrap-projects-keys.mdx b/apps/docs/content/docs/bootstrap-projects-keys.mdx
index 96fd1dc0c..85b78629f 100644
--- a/apps/docs/content/docs/bootstrap-projects-keys.mdx
+++ b/apps/docs/content/docs/bootstrap-projects-keys.mdx
@@ -69,7 +69,7 @@ and display only. Keep deployment, application, node and provider credentials ou
Installation creates no Project or application key. An administrator creates a
Project and issues named keys on the console's **Projects and keys** page, which
-uses the [administrator API](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md), or with that
+uses the [administrator API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md), or with that
API directly.
The Project owns one tenant and one principal; its keys share assets and permissions.
Writes retain each key's provenance. All Projects and application keys live in
@@ -98,4 +98,4 @@ management request points to the console's Core key or Core connection. A resour
deletion conflict must remain visible; it does not authorize an execution call.
Node and daemon `/api/v1` routes and native Runtime interfaces retain their own authentication.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/core-connection.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/core-connection.md)
diff --git a/apps/docs/content/docs/concepts.mdx b/apps/docs/content/docs/concepts.mdx
index 0fccdd135..729007af8 100644
--- a/apps/docs/content/docs/concepts.mdx
+++ b/apps/docs/content/docs/concepts.mdx
@@ -41,7 +41,7 @@ Administrators can still inspect and delete resources in archived Projects.
The Core key is managed separately, in deployment configuration. Key storage,
authentication and audit guarantees are defined by the
-[administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md).
+[administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md).
Parsar product identities, workspaces, business permissions and collaboration
remain outside Core. Parsar is an ordinary API-key holder in a Project.
@@ -93,13 +93,13 @@ copy operation keep their `admin_copy` ownership, distinct from historical unkno
ownership. No request bodies, secrets or file contents enter audit records.
Do not add product users, RBAC, cross-Project shared assets, administrator execution, or old
-private-protocol compatibility to this management model. Developers should follow the [contributor rules](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md) and
+private-protocol compatibility to this management model. Developers should follow the [contributor rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md) and
[Core–Runtime protocol](/runtime-protocol) when implementing these boundaries.
Native failure classification is adapter-owned and uses finite structured native
values. Optional Runtime error metadata is normalized once and retained through
normal delivery and journal draining; it never replaces Core terminal authority,
cancellation receipts, Usage or native identity. See
-[native failure classification](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/native-error-classification.md).
+[native failure classification](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/native-error-classification.md).
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/design-principles.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/design-principles.md)
diff --git a/apps/docs/content/docs/configure.mdx b/apps/docs/content/docs/configure.mdx
index 862bf167b..b11799aca 100644
--- a/apps/docs/content/docs/configure.mdx
+++ b/apps/docs/content/docs/configure.mdx
@@ -117,7 +117,7 @@ output or in Core's settings snapshot. Model providers are not process settings;
The schema is
-[`deploy/install/config.schema.json`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/deploy/install/config.schema.json); each
+[`deploy/install/config.schema.json`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/deploy/install/config.schema.json); each
installation keeps a copy in `generated/config.schema.json` for editors. Core serves
the non-secret settings snapshot, with the path of `config.json` and the apply
command, at `GET /core/v1/installation`.
@@ -134,7 +134,7 @@ Core API with the Core key.
| E2B API key and template build | **System** → **Sandbox backend**: the setup wizard's **E2B cloud** | `/core/v1/sandbox/deployment` | The key is write-only and encrypted |
| Nodes and their capacity | **Nodes**: **Add node**, **Edit node**, **Remove node** on a node's page (**Remove** in its list row) | `/core/v1/sandbox/enrollment-tokens`, `/core/v1/sandbox/nodes` | See [Node capacity](#node-capacity) and the [nodes guide](/hosted-providers) |
| Projects and API keys | **Projects and keys**: **Create project**, **Rename**, **Issue key**, **Revoke**, **Archive** | `/core/v1/projects` | Keys are shown once; Core stores digests |
-| Default model per harness | **System**: **Default model** | `/core/v1/harnesses/{harness}/model-provider` | See [Default models](#default-models) |
+| Default model per harness | **System**: **Default model** | `/core/v1/harnesses/{harness}/model-configuration` | See [Default models](#default-models) |
| Executor credentials of a self-hosted Session | **Session log**, the Session's page: **Executor credentials** | `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | See [self-hosted executors](/self-hosted-execution) |
Which harnesses are enabled, and the default one, are process settings
@@ -146,7 +146,7 @@ Which harnesses are enabled, and the default one, are process settings
Exactly one provider serves the deployment: Docker, microsandbox or E2B. The
deployment specification holds the per-sandbox resources and, for Docker and
microsandbox, the Runtime release. Web's setup proposes the Standard size from
-[`standard-sizes.json`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/web/src/features/sandbox/standard-sizes.json) and
+[`standard-sizes.json`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/src/features/sandbox/standard-sizes.json) and
derives Small and Large from it; the installer applies the bundle's copy of the same
file. The database owns the saved values.
@@ -184,8 +184,8 @@ Current Runtime generation coexistence and ownership-scoped garbage collection
remain supported. They do not upgrade the installed node program or convert an old
installation. History stays, and existing Sessions never move between providers.
See the [nodes guide](/hosted-providers#change-the-sandbox-backend-or-size),
-[operator reference](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
-and [deployment contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/sandbox-deployment.md).
+[operator reference](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
+and [deployment contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/sandbox-deployment.md).
### Node capacity
@@ -212,7 +212,7 @@ Session freezes the provider it starts with, so a later change affects only new
Sessions. Self-hosted Sessions never use it. A hosted or self-hosted Session with no
provider is refused with 400 `model_provider_required`. See
[model providers](/quickstart#model-providers) and the
-[model execution contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md#deployment-defaults).
+[model execution contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md#deployment-defaults).
The operator file `AGENTS_API_EXECUTION_OPTIONS_FILE` is retired; see
[installation version policy](/troubleshooting#installation-version-policy).
@@ -232,7 +232,7 @@ A Web-only installation has only `secrets/core.key`, a copy of its Core's key.
Core reads only its environment. The installer renders `generated/core.env` from
`config.json`; if you run Core yourself (see
-[Maintainers and advanced deployments](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/maintainers.md)), set these variables. Compose
+[Maintainers and advanced deployments](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/maintainers.md)), set these variables. Compose
loads the file with `env_file` and systemd with `EnvironmentFile`, so Compose must be
2.26.0 or newer.
@@ -247,7 +247,7 @@ loads the file with `env_file` and systemd with `EnvironmentFile`, so Compose mu
| `OAC_INSTALLATION_ID` | `state.json`; pinned to the database |
| `OAC_SETTINGS_FILE` | `generated/settings.json`, the snapshot Core serves at `GET /core/v1/installation`; Core does not act on it |
| `OAC_EXECUTION_CONCURRENCY`, `OAC_DEFAULT_HARNESS`, `OAC_HARNESSES`, `OAC_WRITE_AUDIT_RETENTION`, `OAC_OAUTH_TRUSTED_ORIGINS` | The matching `core.*` settings |
-| `OAC_HISTORY_SETTINGS_FILE` | `generated/runtime-history.json` when `core.runtime_history` is set; see the [history contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-history-api.md) |
+| `OAC_HISTORY_SETTINGS_FILE` | `generated/runtime-history.json` when `core.runtime_history` is set; see the [history contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-history-api.md) |
| `OAC_LOG_LEVEL`, `OAC_LOG_FORMAT`, `OAC_LOG_ADD_SOURCE` | `log.*`; Web reads the same three |
| `OAC_E2B_STATE_DIR`, `OAC_E2B_PROVIDER_BIN` | The E2B receipt directory and, for native Core, the bundled helper. The E2B key and template live in the database |
@@ -277,4 +277,4 @@ directory. Core checks the catalog's source revision, Runtime protocol and archi
checksums before serving it. This setting supplies installation artifacts only;
it does not change Runtime preparation, permissions or execution.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/configuration.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/configuration.md)
diff --git a/apps/docs/content/docs/console.mdx b/apps/docs/content/docs/console.mdx
index b418ea4fe..8b5388279 100644
--- a/apps/docs/content/docs/console.mdx
+++ b/apps/docs/content/docs/console.mdx
@@ -27,7 +27,7 @@ management client, and it sends nothing to `/v1`.
| Platform | Projects and keys, Nodes, System | Project and key lifecycle; sandbox deployment and nodes; System: the installation's public address, API base URL, ID and source commit (read-only), each harness's default model provider (write-only key) beside its read-only startup state, the sandbox configuration every Project shares: provider, sandbox size, Runtime or E2B template build, idle suspension and reset, and Core's config.json startup settings with where to change them |
Missing data is shown as missing (—), never as zero. How each figure is read and
-bounded is recorded in [management interface coverage](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/protocol-coverage.md).
+bounded is recorded in [management interface coverage](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/protocol-coverage.md).
## Management scope
@@ -60,15 +60,15 @@ only the console server sends it to Core.
- [Connection and authentication](/bootstrap-projects-keys)
- [Architecture and ownership](/execution-model)
-- [Management interface coverage](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/protocol-coverage.md)
-- [Frontend handoff and acceptance](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/roadmap.md)
-- [React application](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/web/README.md)
+- [Management interface coverage](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/protocol-coverage.md)
+- [Frontend handoff and acceptance](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/roadmap.md)
+- [React application](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/README.md)
-The [administrator API contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) defines
-management routes and resource behavior. The [public API contracts](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md)
+The [administrator API contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) defines
+management routes and resource behavior. The [public API contracts](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md)
define the separate application interface. See the [design principles](/concepts)
-for ownership and [contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md) for required checks.
+for ownership and [contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md) for required checks.
-OpenAgentCore Web is available under the [MIT License](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/LICENSE).
+OpenAgentCore Web is available under the [MIT License](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/LICENSE).
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/README.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/README.md)
diff --git a/apps/docs/content/docs/development.mdx b/apps/docs/content/docs/development.mdx
index 89a09b6c4..405bdb408 100644
--- a/apps/docs/content/docs/development.mdx
+++ b/apps/docs/content/docs/development.mdx
@@ -6,7 +6,7 @@ description: "Set up a checkout and choose the right extension boundary."
This guide is for contributors changing Core, Runtime, adapters, the Web console
or the documentation site. For using a deployment, start with the
[getting started guide](/). Read the
-[contributor rules](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md) before changing code.
+[contributor rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md) before changing code.
## Set up a checkout
@@ -18,8 +18,8 @@ git worktree add ../openagentcore-change -b codex/my-change main
cd ../openagentcore-change
```
-Install Go at the version in [go.mod](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/go.mod), Node 22, pnpm at the version
-in [package.json](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/package.json), and Python 3.9 or newer. The complete gate
+Install Go at the version in [go.mod](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/go.mod), Node 22, pnpm at the version
+in [package.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/package.json), and Python 3.9 or newer. The complete gate
runs on Linux and needs a dedicated PostgreSQL database, OpenSSL development
libraries for the microsandbox helper, and a Playwright browser. Provider and
Runtime builds have additional prerequisites in their component guides.
@@ -65,17 +65,17 @@ under `~/.oac/build/daemon/` by default. `OAC_DEV_HOME` selects another build ro
`OAC_DEV_CORE_BUILD_DIR` selects an absolute Core output directory. Building does
not configure a database, start a deployment or qualify native execution.
-Use the [service guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/README.md#build-standalone-binaries)
+Use the [service guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/README.md#build-standalone-binaries)
to run the Core migrator and server with a separate development database. The
[configuration appendix](/configure#appendix-core-environment-without-the-installer)
owns standalone process settings. For a complete operator installation, use the
[installation guide](/install); building Core alone is a
separate contributor workflow.
-The [Web package guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/web/README.md) describes console development and
+The [Web package guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/README.md) describes console development and
its management-only integration. `pnpm dev:web` starts the frontend development
server; it does not install Core, issue keys or start native execution. The
-[docs app guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/docs/README.md) describes the independent documentation
+[docs app guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/docs/README.md) describes the independent documentation
site; `pnpm dev:docs` starts its development server.
## Repository map
@@ -83,7 +83,7 @@ site; `pnpm dev:docs` starts its development server.
| Location | Responsibility | Read next |
| --- | --- | --- |
| `services/agents-api/internal/api` | Public, administrator and machine HTTP boundaries | [API index](/public-api) |
-| `services/agents-api/internal/store` and `internal/db` | Core persistence, transactions, queries and migrations | [Service guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/README.md#database-ownership) |
+| `services/agents-api/internal/store` and `internal/db` | Core persistence, transactions, queries and migrations | [Service guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/README.md#database-ownership) |
| `services/agents-api/internal/execution` | Durable Turn dispatch and scheduling | [Runtime protocol](/runtime-protocol) |
| `services/agents-api/internal/engine` | Pure qualification of harness operations and placements | [Harness onboarding](/harness-onboarding) |
| `internal/agentdaemon/proto` and `gateway` | Shared wire types, validators and authenticated Runtime connections | [Runtime protocol](/runtime-protocol) |
@@ -91,10 +91,10 @@ site; `pnpm dev:docs` starts its development server.
| `apps/parsar-daemon/internal/agent` | Native harness adapters | [Native references](/harness-onboarding#minimal-runnable-example-and-native-references) |
| `services/agents-api/internal/sandbox` | Provider interfaces and managed compute lifecycle | [Provider onboarding](/sandbox-provider) |
| `services/core-console` | Console login and the server-side management proxy | [Web architecture](/execution-model) |
-| `apps/web` and `packages/agents-client` | Console UI and typed clients | [Web guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/web/README.md) |
-| `deploy/install` and `scripts` | Distribution, installation and validation tools | [Maintainers](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/maintainers.md) |
-| `contracts/agents-api` | Pinned schema, local semantic contracts and qualification evidence | [Coverage ledger](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md) |
-| `apps/docs` | Generated guide and API-reference website | [Generation workflow](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/docs/README.md) |
+| `apps/web` and `packages/agents-client` | Console UI and typed clients | [Web guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/README.md) |
+| `deploy/install` and `scripts` | Distribution, installation and validation tools | [Maintainers](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/maintainers.md) |
+| `contracts/agents-api` | Pinned schema, local semantic contracts and qualification evidence | [Coverage ledger](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md) |
+| `apps/docs` | Generated guide and API-reference website | [Generation workflow](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/docs/README.md) |
Core owns durable execution facts. Runtime owns local execution and cleanup.
Adapters translate native operations. Providers own outer compute. These boundaries
@@ -108,11 +108,11 @@ apply to user-owned machines and Core-managed environments; read the
Start with [Harness onboarding](/harness-onboarding).
Choose a native SDK or machine-readable protocol, declare the operations and
placements you intend to support, and implement the shared
-[`Executor` and `Turn` interfaces](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/harness.go).
+[`Executor` and `Turn` interfaces](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/harness.go).
The guide covers factory registration, service profiles, capability declarations,
input receipts, event translation, cancellation, history and cleanup.
-Use the [synthetic onboarding fixture](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/testdata/onboarding/main.go)
+Use the [synthetic onboarding fixture](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/testdata/onboarding/main.go)
to see the full registration path. With the dedicated test database configured:
```sh
@@ -125,7 +125,7 @@ client, Core, Runtime and a real model. Verify two ordinary Turns, cancellation,
continuation after restart, unknown outcomes and the advertised optional operations.
Record exact native versions and limitations in the linked operation contracts.
-The [Claude bridge guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/packages/claude-sdk-adapter/README.md) explains the
+The [Claude bridge guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/packages/claude-sdk-adapter/README.md) explains the
separate TypeScript SDK process. Codex and MiniMax implementation references are
linked from the onboarding guide. Reuse common process and workspace helpers;
keep native event interpretation inside the adapter.
@@ -149,7 +149,7 @@ native acceptance remains a separate requirement.
### Add a Sandbox Provider
Read [Provider onboarding](/sandbox-provider). Implement
-[`SandboxProvider`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/sandbox/sandbox_provider.go)
+[`SandboxProvider`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/sandbox/sandbox_provider.go)
for the outer compute lifecycle. Register construction and vendor configuration at
that boundary; use optional interfaces for observation and checkpoints. Runtime
capability preparation and native execution keep their existing owners.
@@ -158,7 +158,7 @@ capability preparation and native execution keep their existing owners.
make check-sandbox-provider-contract
```
-Run the [shared contract suite](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/sandbox/contracttest/provider.go)
+Run the [shared contract suite](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/sandbox/contracttest/provider.go)
through the adapter's native boundary, then qualify actual resource creation,
bootstrap, observation, uncertain results and cleanup. Mocked compute cannot prove
that resources were reclaimed or that the outer environment provides isolation.
@@ -166,7 +166,7 @@ that resources were reclaimed or that the outer environment provides isolation.
## Validate a change
Run checks for the affected boundary while developing. The repository
-[required checks](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#required-checks) define completion, including
+[required checks](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#required-checks) define completion, including
`make check` and any changed native component's real acceptance.
| Change | Focused validation |
@@ -192,13 +192,13 @@ with `AGENTS_FIXTURE_PORT` and `AGENTS_WEB_PORT` when running parallel validatio
Keep databases, ports and containers separate between validation workers.
Compilation, fixture success and live model/provider acceptance establish different
facts; report skipped or unavailable checks explicitly. Follow the
-[independent blind review workflow](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#workflow-and-quality)
+[independent blind review workflow](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#workflow-and-quality)
after validation.
## Change documentation
Edit the source that owns the subject, using the
-[documentation ownership map](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#documentation-ownership).
+[documentation ownership map](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#documentation-ownership).
User guides explain a workflow and link to detailed contracts. Contributor rules
explain ownership and required checks. Semantic contracts document exact behavior,
implementation gaps and evidence. Avoid copying the same rule into all three.
@@ -206,9 +206,9 @@ implementation gaps and evidence. Avoid copying the same rule into all three.
Update authored sources before regenerating the docs site. Adding a site page
also requires a source entry and navigation entry; source/output hashes verify
freshness. API references render the namespace-specific generated schemas. Follow
-[the docs app workflow](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/docs/README.md) for link, type, build and browser
+[the docs app workflow](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/docs/README.md) for link, type, build and browser
checks. The release bundle has a separate explicit documentation list in
`scripts/core-distribution-manifest.py`; changing a bundled path or heading must
also pass its relative-link and anchor checks.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/development.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/development.md)
diff --git a/apps/docs/content/docs/environments-and-files.mdx b/apps/docs/content/docs/environments-and-files.mdx
index 7f56c5e2e..665efeddf 100644
--- a/apps/docs/content/docs/environments-and-files.mdx
+++ b/apps/docs/content/docs/environments-and-files.mdx
@@ -3,19 +3,19 @@ title: "Environments and files"
description: "Execution placement, Environment resources and workspace ownership."
---
-This assessment covers the fixed [Python SDK contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream.json), with partial
+This assessment covers the fixed [Python SDK contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream.json), with partial
coverage. Core-managed Docker runs the three qualified native harnesses. V1
user-managed `self_hosted` enrollment uses the same colocated Runtime for Codex,
Claude SDK and MiniMax. `/workspace` names the packaged workspace; a self-hosted
Session may instead select its exact canonical physical directory. The
-[recorded deployment qualification](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/user-managed-runtime-v1.md) retains its historical
+[recorded deployment qualification](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/user-managed-runtime-v1.md) retains its historical
source, paths and tested capability scope.
For hosted compute, the deployment selects E2B, Docker or microsandbox through
-[Hosted Sandbox Manager](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md).
+[Hosted Sandbox Manager](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md).
For the separate caller-managed E2B path, the user owns allocation, renewal and
-cleanup through the official SDK and [Runtime packaging](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/deploy/e2b/README.md).
-[Templates](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-templates.md) remain a hosted-only resource path;
-[Files](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-files.md) reuse the exact authorized local workspace.
+cleanup through the official SDK and [Runtime packaging](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/deploy/e2b/README.md).
+[Templates](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md) remain a hosted-only resource path;
+[Files](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-files.md) reuse the exact authorized local workspace.
The internal Store now owns a durable Environment association for newly created
`self_hosted` and `openai_hosted` snapshots, atomically with Session creation.
@@ -33,7 +33,7 @@ readiness. Rotation/revocation, Session deletion and ownership loss deny further
access without promising immediate cessation of native effects. Native history
remains local to the bound Runtime and cannot be replaced on retry. There is no
registry/Noise relay or transient service-side harness credential.
-See the [enrollment guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/README.md#user-managed-runtime-enrollment).
+See the [enrollment guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/README.md#user-managed-runtime-enrollment).
## Basic public Docker-hosted profile
@@ -41,8 +41,8 @@ An explicitly configured default managed Docker provider enables `type=openai_ho
for the qualified Codex, Claude Code and MiniMax Code profiles. Each uses the same
Runtime lifecycle and workspace interfaces with its native adapter. The outer
Environment provides managed isolation; the daemon adds no inner sandbox.
-See the [engine profile guides](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md#public-engine-profiles) for setup and limits.
-The standalone [operator configuration](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/deploy/codex/README.md#standalone-operator-configuration)
+See the [engine profile guides](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md#public-engine-profiles) for setup and limits.
+The standalone [operator configuration](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/deploy/codex/README.md#standalone-operator-configuration)
selects the qualified immutable Runtime image; advertised capabilities alone do
not enable admission. An idle or initial-text creation commits Session, Environment
and retry identity before the existing leased Worker provisions its allocation.
@@ -63,7 +63,7 @@ rejects explicitly, including null and empty lists, and never invokes apt, sudo
or elevated execution. Package responses include the official required
`system: []` field as empty metadata; it does not enable installation.
Unsupported hostname forms and installation combinations reject explicitly; see
-the [Template coverage and limits](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-templates.md). Empty/null installation
+the [Template coverage and limits](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md). Empty/null installation
defaults produce safe empty metadata, not a live workspace inventory. Service-origin
hosted MCP remains unsupported; Environment Plugin MCP has its
own qualified transport matrix.
@@ -83,11 +83,11 @@ semantics; this profile does not establish complete Environment compatibility.
The application creates, renews and destroys its E2B sandbox through the official
SDK. It deploys the shared Runtime, then enrolls that Runtime into a `self_hosted`
Session. Core neither keeps an E2B allocation nor issues Provider renew/kill calls.
-The [E2B guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/deploy/e2b/README.md) owns packaging and
+The [E2B guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/deploy/e2b/README.md) owns packaging and
user-side lifecycle instructions. Expiry or lost workspace/history must not trigger
-transparent replacement or replay. The [new enrollment qualification](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/user-managed-runtime-v1.md)
+transparent replacement or replay. The [new enrollment qualification](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/user-managed-runtime-v1.md)
records its own real deployment evidence.
-The [prior E2B qualification](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md#e2b-v1-qualification) records a historical
+The [prior E2B qualification](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md#e2b-v1-qualification) records a historical
Core-managed route; it does not establish this caller-managed enrollment result.
Current deployment-managed E2B is a separate hosted configuration in the manager guide.
@@ -125,7 +125,7 @@ connection alone is not readiness. Retries preserve identity and the five-minute
database deadline. HTTP disconnect retains the reservation. Local expired/cancelled
outcomes return 409, lost ownership 503, and deletion 404; exact hosted error
status/body and pending-input crash recovery are unverified. See the
-[canonical wait rules](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#environment-ownership-and-placement).
+[canonical wait rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#environment-ownership-and-placement).
Cancellation-only batches use the existing locked admission and native delivery.
An idle cancellation creates no Turn, and retry identity preserves the original
@@ -200,7 +200,7 @@ Managed Providers remain Linux-only. The daemon does not sandbox tools, files or
network access; tools use the starting account's permissions. Native installation
and current validation limits are in the [native guide](/self-hosted-native).
Historical deployment acceptance does not qualify later platform or capability changes. See the
-[canonical preparation rules](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#shared-runtime-capability-preparation).
+[canonical preparation rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#shared-runtime-capability-preparation).
## Contract inventory
@@ -255,7 +255,7 @@ from Session and Turn status.
## Ownership and placement decision
-The canonical [architecture rules](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#environment-ownership-and-placement)
+The canonical [architecture rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#environment-ownership-and-placement)
keep Environment lifecycle common while leaving process placement and native
transport to adapters. Logical ownership does not require a machine per object.
@@ -279,4 +279,4 @@ native history independently of disposable compute, or prove native restoration;
never treat an Environment ID as a filesystem or history backup. Do not silently
move an existing Session away from its bound device.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environments.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environments.md)
diff --git a/apps/docs/content/docs/execution-model.mdx b/apps/docs/content/docs/execution-model.mdx
index 162c17f4d..5d59dcddf 100644
--- a/apps/docs/content/docs/execution-model.mdx
+++ b/apps/docs/content/docs/execution-model.mdx
@@ -10,7 +10,7 @@ Agents API independently with their own Project keys. The management backend,
`AdminClient` and the React console built on them are implemented.
The [design principles](/concepts) define identity and authority.
-The [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) defines exact
+The [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) defines exact
routes, payloads, pagination and audit records.
## Request boundaries
@@ -106,6 +106,6 @@ comes from the deployment's allocations; the hosted Runtime total counts hosted
observation records across projects and reported lifecycle states. These sources
have different coverage and refresh independently, so the console does not infer
resource retention or cleanup from their difference.
-Native execution ownership remains governed by [CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md).
+Native execution ownership remains governed by [CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md).
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/web/architecture.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/web/architecture.md)
diff --git a/apps/docs/content/docs/harness-onboarding.mdx b/apps/docs/content/docs/harness-onboarding.mdx
index af28187d2..984b0b0fc 100644
--- a/apps/docs/content/docs/harness-onboarding.mdx
+++ b/apps/docs/content/docs/harness-onboarding.mdx
@@ -3,17 +3,17 @@ title: "Add a Harness"
description: "Implement and validate a native Harness adapter."
---
-Start with [`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/harness.go).
+Start with [`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/harness.go).
It defines the required lifecycle, separate optional interfaces and existing
registration methods in one place. Implement one adapter for a native SDK or machine-readable protocol. Core and
Runtime use the common contract; adding a harness should not add engine-name
branches to public handlers, storage, scheduling or environment providers.
-The [harness contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harnesses.md) defines observable behavior. Start with the
+The [harness contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harnesses.md) defines observable behavior. Start with the
[developer guide](/development) for a working checkout; the
-[contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#harness-qualification-and-onboarding)
+[contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#harness-qualification-and-onboarding)
owns architecture and required checks. The pinned public Agents API in
-[upstream.json](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream.json) is separate from the internal adapter protocol.
+[upstream.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream.json) is separate from the internal adapter protocol.
## Ownership
@@ -55,9 +55,36 @@ see [capability preparation](/environments-and-files#runtime-capability-preparat
Model providers supply
model communication configuration, not Turn scheduling or native process ownership.
+## Native model configuration
+
+[`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/harness.go) owns the
+preparation, validation, reserved-field, effective-connection and cleanup contract.
+The shared wire object is `proto.HarnessConfig`. Adapter declarations in
+`internal/harnessconfig/` own these native fields:
+
+| Harness | Accepted native fields | Application |
+| --- | --- | --- |
+| Codex | `model_reasoning_effort`: `none`, `minimal`, `low`, `medium`, `high`, `xhigh` | Native app-server `-c model_reasoning_effort=...` and each Turn's `collaborationMode.settings.reasoning_effort` |
+| Claude SDK | `effort`: `low`, `medium`, `high`, `xhigh`, `max`; `thinking`: the SDK's `adaptive`, `enabled` or `disabled` object | SDK `Options.effort` and `Options.thinking` |
+| MiniMax Code | Empty object only | Existing provider token limits remain required; additional native generation parameters are not qualified |
+
+Claude `thinking` accepts `display` (`summarized` or `omitted`) for adaptive or
+enabled thinking, and an optional positive integer `budgetTokens` only for
+`enabled`. The deprecated `maxThinkingTokens` alternative is rejected.
+These are native settings, not a shared reasoning vocabulary; model availability
+and provider support remain the selected harness's responsibility.
+
+Native protocol and parameter declarations also feed Core administration's small
+configuration-support descriptor. `modeltransport` selects and validates routes
+from those declarations. Its conversion qualification is distinct from adapter
+acceptance and remote-model support. Follow the route and per-input requirements
+in `agent/harness.go`; do not add a second model capability registry or infer
+capabilities from model names. Nonempty `harness_config` currently requires a native
+protocol route because the translator has no loss report for those parameters.
+
## Required adapter interfaces
-[`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/harness.go) is the
+[`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/harness.go) is the
canonical interface entry point. Its required lifecycle is `ExecutorFactory`,
`Executor`, `Turn` and `TurnSettlement`. Optional Turn and workspace interfaces
remain separate; their result types and error values stay in the corresponding
@@ -93,7 +120,7 @@ semantics in each case.
## Events, inputs and optional capabilities
-Use [`internal/agentdaemon/proto`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto) for neutral
+Use [`internal/agentdaemon/proto`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto) for neutral
requests, events and receipts. Each Turn emits only its own events with its Run ID,
in order, and one terminal outcome. Native IDs and usage must be observed rather
than invented. Capture the originating Turn before asynchronous native callbacks;
@@ -147,7 +174,7 @@ still belongs to the service profile and is not granted by Runtime registration.
The static registration surface requires a build. Dynamic plugins are outside
this contract. A small adapter does not remove the need for native qualification.
The runnable test-only example is
-[`testdata/onboarding/main.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/testdata/onboarding/main.go).
+[`testdata/onboarding/main.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/testdata/onboarding/main.go).
It registers a text-only synthetic harness and is never shipped as a real engine.
## Required behavior versus optional operations
@@ -166,14 +193,14 @@ explicitly and record the gap. Never advertise a capability to bypass selection.
Structured-output adapters consume `ExecutionControls.OutputFormat` and publish
confirmed native output through the existing Message contract. Register public
qualification separately from the Runtime capability; see the
-[structured-output boundary](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/structured-output.md). No Core engine-name branch is required.
+[structured-output boundary](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/structured-output.md). No Core engine-name branch is required.
Initial requests, `Executor.StartTurn` and steering consume the same ordered
`proto.MessageInput`. Text-only adapters use `TextOnly()` to reject images without
discarding content. Image adapters translate each part natively and acknowledge
an active batch only after all its messages are applied. Register
`MessageImages` and qualify `MessageImagePlacements` separately; see the
-[message-input contract and real acceptance](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/message-input.md).
+[message-input contract and real acceptance](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md).
Hosted workspace execution additionally requires verified preparation, workspace
reads/output export, network behavior and credential/history isolation. Reuse the
@@ -205,7 +232,7 @@ it does not expand to match another harness's feature list.
development, then `make check` and applicable real regressions. API changes
require `make openapi`; query changes require `make sqlc-generate`.
- Review: follow the repository
- [blind review workflow](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md#workflow-and-quality).
+ [blind review workflow](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#workflow-and-quality).
Record exact revisions, image/package versions, commands, results and limits.
Keep keys in private operator files; never commit them or include them in logs or
@@ -215,7 +242,7 @@ full board. Acceptance of one engine is not complete public protocol compatibili
## Minimal runnable example and native references
-[`testdata/onboarding/main.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/testdata/onboarding/main.go)
+[`testdata/onboarding/main.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/testdata/onboarding/main.go)
is a runnable synthetic adapter. It demonstrates registration, a Session-owned
Executor, fresh Turns, durable steering, cancellation and history binding through
the actual gateway and Router. Run `TestThirdHarnessPublicOnboarding` against a
@@ -224,18 +251,18 @@ not shipped and is not evidence for a real SDK or sandbox.
Use the native adapters as implementation references after choosing a native API:
-- [Codex](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/codex/executor.go): app-server transport.
-- [Claude](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/claudesdk/executor.go): Go ownership and a [TypeScript SDK bridge](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/packages/claude-sdk-adapter/README.md).
-- [MiniMax](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/agent/mcode): ACP and native workspace companion.
+- [Codex](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/codex/executor.go): app-server transport.
+- [Claude](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/claudesdk/executor.go): Go ownership and a [TypeScript SDK bridge](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/packages/claude-sdk-adapter/README.md).
+- [MiniMax](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/agent/mcode): ACP and native workspace companion.
Start with the mandatory text lifecycle, then qualify optional operations using
-[harness coverage](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harnesses.md) and each operation's contract. Do not copy an
+[harness coverage](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harnesses.md) and each operation's contract. Do not copy an
adapter's native limitations into the shared Core protocol.
## Optional Subagent observations
A harness that supports the Subagent resource reads implements the existing
-[neutral observation contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/subagents.md#common-adapter-contract). It reports
+[neutral observation contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/subagents.md#common-adapter-contract). It reports
verified child identity, lifecycle effects and owned Turn/Item history through
the authenticated Run, then qualifies those facts with real execution. It does
not add routes, storage branches or a harness-specific Core scheduler. Report
@@ -254,4 +281,4 @@ installation; adapters own native layout and probes. Validate installation and
actual execution on each advertised platform. Missing or incompatible native
content must fail, never install itself during a Turn.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harness-onboarding.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-onboarding.md)
diff --git a/apps/docs/content/docs/hosted-providers.mdx b/apps/docs/content/docs/hosted-providers.mdx
index 725e20fbb..87491b15b 100644
--- a/apps/docs/content/docs/hosted-providers.mdx
+++ b/apps/docs/content/docs/hosted-providers.mdx
@@ -10,7 +10,7 @@ With E2B you need no nodes. Self-hosted executors, which applications run for th
own Sessions, are a different thing; see [Self-hosted executors](/self-hosted-execution).
You add a node by generating a command in Web and pasting it on the host. The
-[operator reference](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md) covers the
+[operator reference](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md) covers the
node protocol, manual registration, placement and failure handling.
## Before you add a node
@@ -165,7 +165,7 @@ The installation ID is in the command (`--installation-id`) and on the **System*
1. In Web, open **Nodes** and choose **Remove node** on the node's page, or
**Remove** in its list row, then **Confirm removal**. Core refuses while the node
still holds sandboxes, snapshots or pending cleanup; let them finish, or
- [archive their Sessions](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
+ [archive their Sessions](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
through the Core API. Removal is permanent: the host can come back only as a new
node.
2. Web then shows **Clean up the host** with the uninstall command. Run it on the host:
@@ -265,7 +265,7 @@ files. Shared daemon images remain; a host administrator may remove them only af
confirming no installation still needs them. Microsandbox image cleanup remains
scoped to the installation's private native store and verified ownership receipts.
-The [operator reference](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
+The [operator reference](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#removal-and-reset)
describes reset and API behavior. Same-team E2B edits have a separate online Core
API path and do not involve node installation.
@@ -278,4 +278,4 @@ convert or delete it. Preserve the old installation, Runtime resources and histo
provision a fresh node separately through **Add node**. The current installer does
not adopt historical resources or remove another installation's state.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/nodes.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/nodes.md)
diff --git a/apps/docs/content/docs/index.mdx b/apps/docs/content/docs/index.mdx
index ebc0d72a2..a4111b092 100644
--- a/apps/docs/content/docs/index.mdx
+++ b/apps/docs/content/docs/index.mdx
@@ -30,7 +30,7 @@ for the documentation website; generated site pages are not a second manual.
The [user guide](/user-guide) connects common tasks to their detailed contracts.
The [API index](/public-api) identifies each caller and credential. Use the
-[coverage record](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md) to check operation support
+[coverage record](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md) to check operation support
and Harness differences before relying on an optional feature.
## Extend Core
@@ -38,7 +38,7 @@ and Harness differences before relying on an optional feature.
Start with the [developer guide](/development). It links the repository map,
required checks and extension points for Harness adapters, Runtime implementations
and Sandbox Providers. Architecture rules live in
-[CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md); distribution and release procedures live in
-[the maintainer guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/maintainers.md).
+[CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md); distribution and release procedures live in
+[the maintainer guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/maintainers.md).
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/README.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/README.md)
diff --git a/apps/docs/content/docs/install-options.mdx b/apps/docs/content/docs/install-options.mdx
index bdd5f4f75..3a6239302 100644
--- a/apps/docs/content/docs/install-options.mdx
+++ b/apps/docs/content/docs/install-options.mdx
@@ -68,4 +68,4 @@ See [deployment modes](/install#modes), [native Core](/install#native-core) and
Several installations can share a machine when they use distinct installation
directories and ports. Each has its own database, Core key and node registrations.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/install-options.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/install-options.md)
diff --git a/apps/docs/content/docs/install.mdx b/apps/docs/content/docs/install.mdx
index 7f0bd261a..4d3a39342 100644
--- a/apps/docs/content/docs/install.mdx
+++ b/apps/docs/content/docs/install.mdx
@@ -127,7 +127,7 @@ A deployment runs its sandboxes on exactly one backend:
| `none` | Nothing yet | Choose the backend on the **Nodes** page in Web |
The Standard sizes come from the bundle's copy of Web's
-[`standard-sizes.json`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/web/src/features/sandbox/standard-sizes.json). The
+[`standard-sizes.json`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/src/features/sandbox/standard-sizes.json). The
installer saves the choice through the same administrator API that Web uses once the
services are healthy. If Core refuses it, for example because E2B rejects the key,
the installer prints Core's message and exits with an error; the services keep
@@ -151,7 +151,7 @@ it installs anything:
```
Prepare the template build with the
-[E2B guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/deploy/e2b/README.md). To change the backend or
+[E2B guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/deploy/e2b/README.md). To change the backend or
the sandbox size later, use the Nodes page in Web; see
[Nodes](/hosted-providers#change-the-sandbox-backend-or-size).
@@ -510,4 +510,4 @@ missing images, restores a missing `oac` command, copies node files newly placed
`--install-dir`. It refuses a bundle from another release; see
[installation version policy](/troubleshooting#installation-version-policy).
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/install.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/install.md)
diff --git a/apps/docs/content/docs/observability.mdx b/apps/docs/content/docs/observability.mdx
index 6fdf78d3c..1f3791f5a 100644
--- a/apps/docs/content/docs/observability.mdx
+++ b/apps/docs/content/docs/observability.mdx
@@ -7,7 +7,7 @@ Status: Phase 2 and initial Core Web consumption implemented. The current-snapsh
`packages/agents-client` projection, and generated `core.openapi.yaml` contract are
implemented and consumed by the Dashboard through complete Session/observation
identity joins. Durable history uses the separate optional
-[Runtime history API](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-history-api.md); lifecycle controls remain outside
+[Runtime history API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-history-api.md); lifecycle controls remain outside
this phase.
These are administrator reads under `/core/v1`, authenticated by the Core key,
@@ -92,7 +92,7 @@ Authorization: Bearer ...
```
This returns the same object shape as a list item's `observation`, without the
-administrator list's `disk` (see the [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md)). It never starts a Turn, creates
+administrator list's `disk` (see the [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md)). It never starts a Turn, creates
an Environment, provisions compute, renews a lease, or changes lifecycle state.
A valid `environment:none` Session returns `200` with status `unsupported`; the
@@ -193,7 +193,7 @@ Use the existing Agents API error envelope.
| 400 | `invalid_request_error` / `invalid_request_error` | List: a repeated supported query key, or an empty or invalid limit or order, with the shared Beta list messages. Unknown list query keys are ignored. |
| 400 | `invalid_request_error` / `unsupported_parameter` | Single-Session retrieval with any query parameter. |
| 401 | `invalid_request_error` / `invalid_admin_key` | Missing or invalid Core key. |
-| 404 | `not_found_error` / `not_found_error` | Missing, malformed or foreign Session/cursor, indistinguishably, as for the [Session list cursor](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/list-query-semantics.md#list-cursor-errors--september-23-2026). |
+| 404 | `not_found_error` / `not_found_error` | Missing, malformed or foreign Session/cursor, indistinguishably, as for the [Session list cursor](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/list-query-semantics.md#list-cursor-errors--september-23-2026). |
| 500 | `server_error` / `internal_error` | Integrity, ownership, or invalid provider evidence. |
| 503 | `server_error` / `execution_unavailable` | Required Runtime observation service is not configured, or list collection exceeded its request budget. |
@@ -273,10 +273,10 @@ deletion makes the candidate incomplete and prevents publication.
- Token usage: use existing Session/Turn Usage.
- Billing and cost: product/backend concern.
- Historical series in these routes: the optional capability uses the separate
- [Runtime history API](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-history-api.md).
+ [Runtime history API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-history-api.md).
- Container logs and command output.
- Provider credentials or native configuration.
- Start, stop, pause, resume, restart, renew, or delete operations.
- Idle classification and automatic shutdown.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-observability-api.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-observability-api.md)
diff --git a/apps/docs/content/docs/public-api.mdx b/apps/docs/content/docs/public-api.mdx
index 51e2a1acd..22d07479a 100644
--- a/apps/docs/content/docs/public-api.mdx
+++ b/apps/docs/content/docs/public-api.mdx
@@ -9,9 +9,9 @@ installer downloads are public release content.
| Namespace | Caller | Credential | Contents | Reference |
| --- | --- | --- | --- | --- |
-| `/v1` | Applications (business systems, SDKs) | Project API key | Exactly the pinned official Agents API routes. Core-only fields live only in `x_agents_core` (`harness`, `model_provider`, Session `installation`) | [Public API](/sessions) |
-| `/core/v1` | Core Web's server and operator scripts | [Core key](/troubleshooting#core-key) | Installation facts, Projects and keys, resource reads and deletion, Session archive, credential issuance, metrics, audit, sandbox deployment and nodes, deployment model providers | [Core API](#core-api), [Web API](/admin-api), [Core OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core.openapi.yaml) |
-| `/api/v1` | Nodes, Runtime daemons, self-hosted executors | Machine credentials: short-lived Session installation grants, node enrollment tokens and executor credentials issued through `/core/v1` or claimed by installation, node credentials registered with an enrollment token, and daemon credentials Core writes into hosted sandboxes | Machine bootstrap and connections: `/api/v1/sandbox-node/*` and `/api/v1/agent-daemon/*`, including WebSockets; each credential works only on its own routes | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host), [executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime.openapi.yaml) |
+| `/v1` | Applications (business systems, SDKs) | Project API key | Exactly the pinned official Agents API routes. Core-only fields live only in `x_agents_core` (`harness`, `model_provider`, `harness_config`, Session `installation`) | [Public API](/sessions) |
+| `/core/v1` | Core Web's server and operator scripts | [Core key](/troubleshooting#core-key) | Installation facts, Projects and keys, resource reads and deletion, Session archive, credential issuance, metrics, audit, sandbox deployment and nodes, deployment model providers | [Core API](#core-api), [Web API](/admin-api), [Core OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core.openapi.yaml) |
+| `/api/v1` | Nodes, Runtime daemons, self-hosted executors | Machine credentials: short-lived Session installation grants, node enrollment tokens and executor credentials issued through `/core/v1` or claimed by installation, node credentials registered with an enrollment token, and daemon credentials Core writes into hosted sandboxes | Machine bootstrap and connections: `/api/v1/sandbox-node/*` and `/api/v1/agent-daemon/*`, including WebSockets; each credential works only on its own routes | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host), [executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime.openapi.yaml) |
A Project API key gets 401 on `/core/v1` and `/api/v1`; the Core key gets 401 on
`/v1` and `/api/v1`. Projects own assets. Multiple equally privileged keys share
@@ -35,7 +35,7 @@ with the Core key on Core's loopback port, not through the public entry.
Applications call every `/v1` route with a Project API key. The routes are exactly
the 58 method and path pairs in
-[upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream-routes.json); the
+[upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json); the
[Public API guide](/sessions) groups them by resource. `/v1` has no
Core-only route.
@@ -46,18 +46,18 @@ with the Core key.
| Routes | Contents | Contract |
| --- | --- | --- |
-| `projects`, `projects/{project_id}[/archive]`, `projects/{project_id}/keys[/{key_id}]` | Projects and their API keys | [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) |
-| `projects/{project_id}/{agents,environment-templates,skills,files,vaults,sessions}/**` | Resource reads and deletion, Session history, artifacts and archive | [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) |
-| `projects/{project_id}/sessions/{session_id}/execution-configuration` | Committed harness and model selection | [Execution configuration](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/execution-configuration.md) |
-| `projects/{project_id}/sessions/{session_id}/diagnostics`, `projects/{project_id}/sessions/{session_id}/turns/{turn_id}/diagnostics` | Root failure categories and Item receipt timing | [Session diagnostics](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/session-diagnostics.md) |
+| `projects`, `projects/{project_id}[/archive]`, `projects/{project_id}/keys[/{key_id}]` | Projects and their API keys | [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) |
+| `projects/{project_id}/{agents,environment-templates,skills,files,vaults,sessions}/**` | Resource reads and deletion, Session history, artifacts and archive | [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) |
+| `projects/{project_id}/sessions/{session_id}/execution-configuration` | Committed harness and model selection | [Execution configuration](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/execution-configuration.md) |
+| `projects/{project_id}/sessions/{session_id}/diagnostics`, `projects/{project_id}/sessions/{session_id}/turns/{turn_id}/diagnostics` | Root failure categories and Item receipt timing | [Session diagnostics](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/session-diagnostics.md) |
| `projects/{project_id}/sessions/{session_id}/runtime-observation`, `sandbox/runtime-observations` | Current Runtime observations | [Runtime observations](/observability) |
-| `projects/{project_id}/sessions/{session_id}/runtime-history` | Stored Runtime history | [Runtime history](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-history-api.md) |
-| `projects/{project_id}/{resource-owners,write-operations}`, `audit-log`, `summary` | Provenance, write history, administrator audit and usage summary | [Write audit](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/write-audit.md), [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) |
-| `projects/{project_id}/environments/{environment_id}/executor-credentials[/{key_id}]` | Executor credentials for a self-hosted Environment | [Executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md) |
-| `installation` | Public URL, API base URL, source commit, the installer's process settings and what is bound to the public URL; available before any deployment | [Installation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/installation.md) |
-| `metrics` | Core's own process metrics | [Core metrics](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core-metrics.md) |
-| `sandbox/deployment[/reset]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Sandbox deployment, node enrollment tokens and nodes | [Sandbox deployment](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/sandbox-deployment.md), [node operations](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md), [node host history](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/node-host-history.md) |
-| `harnesses`, `harnesses/{harness}/model-provider` | Supported harnesses and each harness's deployment default model provider (write-only key) | [Model execution](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md#deployment-defaults) |
+| `projects/{project_id}/sessions/{session_id}/runtime-history` | Stored Runtime history | [Runtime history](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-history-api.md) |
+| `projects/{project_id}/{resource-owners,write-operations}`, `audit-log`, `summary` | Provenance, write history, administrator audit and usage summary | [Write audit](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/write-audit.md), [administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) |
+| `projects/{project_id}/environments/{environment_id}/executor-credentials[/{key_id}]` | Executor credentials for a self-hosted Environment | [Executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md) |
+| `installation` | Public URL, API base URL, source commit, the installer's process settings and what is bound to the public URL; available before any deployment | [Installation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/installation.md) |
+| `metrics` | Core's own process metrics | [Core metrics](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-metrics.md) |
+| `sandbox/deployment[/reset]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Sandbox deployment, node enrollment tokens and nodes | [Sandbox deployment](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/sandbox-deployment.md), [node operations](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md), [node host history](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/node-host-history.md) |
+| `harnesses`, `harnesses/{harness}/model-configuration` | Supported harnesses and each harness's deployment default model configuration (write-only provider key) | [Model execution](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md#deployment-defaults) |
## Machine connection API
@@ -66,41 +66,41 @@ the Core key or a Project API key.
| Routes | Caller | Credential | Contract |
| --- | --- | --- | --- |
-| `POST sandbox-node/enroll` | Node installer | One-use enrollment token from `POST /core/v1/sandbox/enrollment-tokens` | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime.openapi.yaml) |
-| `GET sandbox-node/configuration` | Node installer and node | Enrollment token, or node credential with `X-OAC-Node-ID` | [Sandbox deployment](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/sandbox-deployment.md), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime.openapi.yaml) |
-| `GET sandbox-node/identity`, WebSocket `GET sandbox-node/connect` | Node | Node credential registered at enrollment | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host) |
-| `POST agent-daemon/enroll`, `GET agent-daemon/connection` | Self-hosted executor and its installer | Executor credential from `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | [Executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md) |
-| WebSocket `GET agent-daemon/ws`, `POST agent-daemon/bootstrap`, `GET agent-daemon/device-status` | Runtime daemons | Daemon credential: Core writes one into each hosted sandbox it prepares; a self-hosted executor uses its executor credential | [Runtime enrollment](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/README.md#user-managed-runtime-enrollment) |
+| `POST sandbox-node/enroll` | Node installer | One-use enrollment token from `POST /core/v1/sandbox/enrollment-tokens` | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime.openapi.yaml) |
+| `GET sandbox-node/configuration` | Node installer and node | Enrollment token, or node credential with `X-OAC-Node-ID` | [Sandbox deployment](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/sandbox-deployment.md), [machine OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime.openapi.yaml) |
+| `GET sandbox-node/identity`, WebSocket `GET sandbox-node/connect` | Node | Node credential registered at enrollment | [Node operations](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host) |
+| `POST agent-daemon/enroll`, `GET agent-daemon/connection` | Self-hosted executor and its installer | Executor credential from `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | [Executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md) |
+| WebSocket `GET agent-daemon/ws`, `POST agent-daemon/bootstrap`, `GET agent-daemon/device-status` | Runtime daemons | Daemon credential: Core writes one into each hosted sandbox it prepares; a self-hosted executor uses its executor credential | [Runtime enrollment](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/README.md#user-managed-runtime-enrollment) |
## Contract sources
-- [Pinned upstream baseline](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream.json): OpenAI
+- [Pinned upstream baseline](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream.json): OpenAI
Python SDK 3.13.0, exact upstream commit and `agents=v1`.
-- [Pinned routes](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream-routes.json) and
- [fields](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream-fields.json): extracted from the
+- [Pinned routes](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json) and
+ [fields](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-fields.json): extracted from the
pinned SDK by `scripts/extract-agents-api-upstream.py`. Contract tests require the
public OpenAPI to have exactly these routes and to keep every other field inside
`x_agents_core`.
-- [Public OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/openapi.yaml): public schema snapshot;
- combine it with the fixed SDK and [operation evidence](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/operation-evidence.md).
-- [Core OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core.openapi.yaml): generated `/core/v1`
+- [Public OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/openapi.yaml): public schema snapshot;
+ combine it with the fixed SDK and [operation evidence](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/operation-evidence.md).
+- [Core OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core.openapi.yaml): generated `/core/v1`
routes, all authenticated by the Core key.
-- [Machine connection OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime.openapi.yaml):
- generated `/api/v1` sandbox node routes. The node WebSocket is described in the [generation protocol](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/node-generation-protocol.md); the private
+- [Machine connection OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime.openapi.yaml):
+ generated `/api/v1` sandbox node routes. The node WebSocket is described in the [generation protocol](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/node-generation-protocol.md); the private
daemon transport is described in the Runtime credential guide.
-- [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md): Project/key
+- [Administrator contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md): Project/key
lifecycle, resources, explicit hosted Session archive, summary,
errors/deletion preconditions, audit and historical copy provenance.
- [Web integration](/admin-api): browser, console and Core boundaries and frontend handoff.
-- [Design rules](/concepts) and [contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/CONTRIBUTING.md):
+- [Design rules](/concepts) and [contributor guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md):
ownership, security and change requirements.
Generated schemas do not establish complete compatibility or real execution
-support. The [coverage record](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md) identifies
+support. The [coverage record](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md) identifies
qualified workflows, native differences and unresolved behavior. Update the
relevant contract and this index when adding or moving an API surface.
-Core administration failures use the [Core error envelope](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core-errors.md),
+Core administration failures use the [Core error envelope](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-errors.md),
including typed optional safe details and distinct console proxy rejection codes.
The public and machine error contracts remain unchanged.
@@ -115,4 +115,4 @@ subroute with the installation Bearer authorization. Qualified artifacts beneath
See [native self-hosted installation](/self-hosted-native) for expiry, retry,
credential ownership and platform rules.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/api/README.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/api/README.md)
diff --git a/apps/docs/content/docs/quickstart.mdx b/apps/docs/content/docs/quickstart.mdx
index a1e930134..fe80bb1da 100644
--- a/apps/docs/content/docs/quickstart.mdx
+++ b/apps/docs/content/docs/quickstart.mdx
@@ -115,8 +115,8 @@ The provider's protocol must match the harness:
| Claude Code (`claude_sdk`) | `anthropic` | The provider's exact model ID |
| MiniMax Code (`mcode`) | `anthropic` | `context_window` and `max_output_tokens` |
-See [harness selection](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harness-selection.md) and
-[model execution](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md) for the full contract.
+See [harness selection](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-selection.md) and
+[model execution](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md) for the full contract.
Selecting a harness doesn't make an unsupported model or operation work.
## Model providers
@@ -172,8 +172,8 @@ file. A timeout does not cancel the task or prove failure. The
add Skills/Plugins/MCP, cancel work and recover after disconnection.
Files, Artifacts, cancellation and their current limits are in the
-[coverage ledger](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md). MCP credentials use the
+[coverage ledger](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md). MCP credentials use the
separate Vault API; they are neither Project API keys nor model provider keys. The
[API index](/public-api) lists every route.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/quickstart.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/quickstart.md)
diff --git a/apps/docs/content/docs/runtime-protocol.mdx b/apps/docs/content/docs/runtime-protocol.mdx
index c64bdd5ea..03f7537a5 100644
--- a/apps/docs/content/docs/runtime-protocol.mdx
+++ b/apps/docs/content/docs/runtime-protocol.mdx
@@ -5,10 +5,10 @@ description: "Runtime lifecycle, messages, receipts and recovery."
This is the integration entry point for a Runtime that executes work for Core.
The wire definitions live once in
-[`internal/agentdaemon/proto`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto);
-Core's [gateway](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/gateway) and the reference Runtime's
-[dispatcher](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/dispatch) both use them.
-The [machine HTTP API](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime.openapi.yaml) describes
+[`internal/agentdaemon/proto`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto);
+Core's [gateway](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/gateway) and the reference Runtime's
+[dispatcher](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/dispatch) both use them.
+The [machine HTTP API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime.openapi.yaml) describes
registration and connection endpoints. This document defines the meaning and
ordering of the messages after connection; it does not replace the typed payloads.
@@ -46,7 +46,7 @@ preparation is not proof of containment.
5. Dispatch ordered JSON envelopes over the connection. Heartbeats establish
liveness only, not execution progress or a receipt for earlier messages.
-The wire version is [`proto.Version`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/version.go),
+The wire version is [`proto.Version`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/version.go),
independent of the Runtime build version reported in heartbeats. Core accepts
only an exact match, including the patch component. A mismatch returns HTTP 426
`incompatible_version` before dispatch; the daemon treats it as permanent and
@@ -62,7 +62,7 @@ Session or Environment binding.
## Envelope and identity
Every data frame is one JSON
-[`Envelope`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/envelope.go):
+[`Envelope`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/envelope.go):
`type`, type-dependent `id`, typed `payload`, and optional W3C `trace`.
Trace is diagnostic correlation only; missing or invalid trace data creates a
local trace and never changes ownership. Do not use a trace ID as a request ID.
@@ -91,16 +91,16 @@ finite error categories. There is no parallel payload schema to keep in sync.
| Core → Runtime | Runtime → Core | Definition |
| --- | --- | --- |
-| `runtime_prepare` | `runtime_prepare_result` | [Initialization and capability transfer](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/runtime_prepare.go) |
-| `execution_prepare`, `execution_start`, `execution_release` | `preparation_status` | [Execution admission](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/preparation.go) |
-| `prompt_request`, `prompt_cancel`, `device_shutdown` | `delta`, `thinking`, `output_message`, `tool_call`, `usage`, `error`, `done`, `heartbeat` | [Requests](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/outbound.go), [events and capabilities](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/inbound.go) |
-| `permission_decision`, `prompt_for_user_choice_decision` | `permission_request`, `permission_cancel`, `prompt_for_user_choice`, `interaction_decision_ack` | [Requests](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/outbound.go), [interactions](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/inbound.go) |
-| `prompt_steer` | `prompt_steer_ack` | [Active input receipts](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/steering.go) |
-| `function_result` | `function_call`, `interaction_decision_ack` | [Function calls](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/functions.go) |
-| `workspace_read`, `workspace_write`, `workspace_export` | Matching `*_result` | [Read](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/workspace_read.go), [write](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/workspace_write.go), [export](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/workspace_export.go) |
-| `environment_quiesce`, `environment_resume` | `environment_quiesced`, `environment_resumed` | [Suspension fencing](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/suspend.go) |
-
-Initial and active input share [ordered MessageInput](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/internal/agentdaemon/proto/message_input.go).
+| `runtime_prepare` | `runtime_prepare_result` | [Initialization and capability transfer](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/runtime_prepare.go) |
+| `execution_prepare`, `execution_start`, `execution_release` | `preparation_status` | [Execution admission](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/preparation.go) |
+| `prompt_request`, `prompt_cancel`, `device_shutdown` | `delta`, `thinking`, `output_message`, `tool_call`, `usage`, `error`, `done`, `heartbeat` | [Requests](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/outbound.go), [events and capabilities](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/inbound.go) |
+| `permission_decision`, `prompt_for_user_choice_decision` | `permission_request`, `permission_cancel`, `prompt_for_user_choice`, `interaction_decision_ack` | [Requests](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/outbound.go), [interactions](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/inbound.go) |
+| `prompt_steer` | `prompt_steer_ack` | [Active input receipts](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/steering.go) |
+| `function_result` | `function_call`, `interaction_decision_ack` | [Function calls](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/functions.go) |
+| `workspace_read`, `workspace_write`, `workspace_export` | Matching `*_result` | [Read](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/workspace_read.go), [write](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/workspace_write.go), [export](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/workspace_export.go) |
+| `environment_quiesce`, `environment_resume` | `environment_quiesced`, `environment_resumed` | [Suspension fencing](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/suspend.go) |
+
+Initial and active input share [ordered MessageInput](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/internal/agentdaemon/proto/message_input.go).
Adapters preserve message/content order and explicitly reject unsupported content.
Usage frames and the final usage snapshot replace earlier cumulative snapshots;
do not add them. An absent measurement is unknown, not zero.
@@ -177,7 +177,7 @@ truth and reconciles from confirmed facts. Runtime retains cleanup ownership
until native work, input receipts, interactions and child work have settled.
The public Turn status is a separate, existing projection:
-[`execution/delivery.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/execution/delivery.go)
+[`execution/delivery.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/execution/delivery.go)
records an unsuccessful orchestration attempt as `failed`, including
`delivery_unknown` after an unconfirmed send and `event_stream_incomplete`
after subscription failure. A closed subscription can replace the send reason
@@ -211,8 +211,8 @@ Provider's confirmed reclamation of compute.
Run `make check-runtime-contract` from the repository root. It exercises the
shared wire validators, gateway, transport and dispatcher, plus
-[real WebSocket contract scenarios](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/apps/parsar-daemon/internal/contracttest/wire_test.go)
-using a controlled Harness adapter, plus the [observation-result regression](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/execution/runtime_protocol_test.go). It requires no model credentials or external
+[real WebSocket contract scenarios](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/parsar-daemon/internal/contracttest/wire_test.go)
+using a controlled Harness adapter, plus the [observation-result regression](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/execution/runtime_protocol_test.go). It requires no model credentials or external
sandbox. These tests are also included in `make check` through `check-go` and
`check-agents-api`.
@@ -228,4 +228,4 @@ controlled-adapter test establishes the transport contract, not native Harness
behavior, OS support, provider authentication or sandbox isolation. Update the
shared types, this guide and the contract checks together when semantics change.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/runtime-protocol.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/runtime-protocol.md)
diff --git a/apps/docs/content/docs/sandbox-provider.mdx b/apps/docs/content/docs/sandbox-provider.mdx
index 4858685c5..d8e341529 100644
--- a/apps/docs/content/docs/sandbox-provider.mdx
+++ b/apps/docs/content/docs/sandbox-provider.mdx
@@ -3,7 +3,7 @@ title: "Add a Sandbox Provider"
description: "Environment allocation, bootstrap and reclamation."
---
-Start at [`sandbox_provider.go`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/sandbox/sandbox_provider.go).
+Start at [`sandbox_provider.go`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/sandbox/sandbox_provider.go).
It defines the required `SandboxProvider` and optional `CheckpointProvider`
interfaces. Use the existing types; do not introduce another lifecycle protocol or
an execution path for a particular vendor.
@@ -33,7 +33,7 @@ Do not implement an optional interface with successful no-op methods. Core uses
interface assertions to select optional operations. Advertised support requires
contract and native acceptance evidence; a healthy node or an available CLI does
not establish it. Observation never renews a lease, starts compute or prepares a
-Harness. See the [observation contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/runtime-observability.md).
+Harness. See the [observation contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/runtime-observability.md).
`RunCommand` is an existing administrative bootstrap/diagnostic facility, not an
alternate route for Skills, Plugins, MCP setup, initial files, Session execution or
@@ -48,12 +48,12 @@ Registration is explicit construction, not an init-time plugin registry:
configuration in an adapter package under `services/agents-api/internal/sandbox`.
Assert `var _ sandbox.SandboxProvider = (*YourAdapter)(nil)` at compile time.
2. For a node-local adapter, add its typed construction and readiness probe in
- [`sandbox/config`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/sandbox/config/config.go).
+ [`sandbox/config`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/sandbox/config/config.go).
The existing `Built` result returns the provider, probe, installation identity,
backend fingerprint and specification digest; the factory also returns its
close function. Construction must not create an Environment.
3. For a direct adapter, register its construction in
- [`managedSetup.provider`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/cmd/server/managed_setup.go).
+ [`managedSetup.provider`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/cmd/server/managed_setup.go).
Node-local adapters are selected there through the existing node proxy. Keep
vendor-specific deployment validation and SDK setup at this boundary.
4. Preserve the existing `execution.RuntimeProvider` deployment binding:
@@ -143,7 +143,7 @@ Persist operation IDs and provider-returned snapshot provenance unchanged.
another capture or restore. `ResumeCompute` only thaws the retained source; it
must not cold-start a stopped one. Cleanup targets the exact compute incarnation
and snapshot, not whichever instance currently has the same display name. See
-[the lifecycle implementation](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/execution/runtime_compute.go)
+[the lifecycle implementation](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/execution/runtime_compute.go)
and its failure tests before advertising this capability.
## Four distinct readiness facts
@@ -164,7 +164,7 @@ A provider must not implement a competing preparation path.
## Validate the integration
Run `make check-sandbox-provider-contract` while developing. It runs the shared
-[`contracttest`](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/services/agents-api/internal/sandbox/contracttest) suite through
+[`contracttest`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/internal/sandbox/contracttest) suite through
real adapter boundaries using controlled native failures, plus existing adapter
and node transport tests. The same packages are included in `make check`.
New adapters should call the public failure runner with native-side fixtures,
@@ -185,4 +185,4 @@ SDK helper tests use `make check-e2b-provider` and
`make check-microsandbox-provider`. Passing controlled contract tests is not a
claim of live cloud or model acceptance.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/sandbox-provider.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/sandbox-provider.md)
diff --git a/apps/docs/content/docs/self-hosted-execution.mdx b/apps/docs/content/docs/self-hosted-execution.mdx
index b0f7b3756..6a3c53f4f 100644
--- a/apps/docs/content/docs/self-hosted-execution.mdx
+++ b/apps/docs/content/docs/self-hosted-execution.mdx
@@ -97,7 +97,7 @@ from tools running as the same user.
Closing an executor, cancelling a Turn or losing its connection preserves the
snapshot and workspace. The compute owner remains responsible for explicit
-cleanup. [Historical qualification](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/user-managed-runtime-v1.md)
+cleanup. [Historical qualification](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/user-managed-runtime-v1.md)
records only its stated inputs and binaries; it does not qualify the current native
platforms or local capability preparation.
@@ -123,7 +123,7 @@ or rotated; revocation remains available.
Operators can still issue, rotate or revoke executor credentials using a Core key
through Core's loopback port. This is not required for one-command onboarding.
-See the [credential contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md)
+See the [credential contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md)
for those routes and uncertain-response handling.
## Historical executor installations
@@ -134,4 +134,4 @@ and native history; use a fresh Runtime home and Session when moving versions.
Historical container-installer instructions and qualification records describe
those earlier artifacts, not acceptance of the current native daemon.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/self-hosted.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/self-hosted.md)
diff --git a/apps/docs/content/docs/self-hosted-native.mdx b/apps/docs/content/docs/self-hosted-native.mdx
index 748b2cbbf..92342f6db 100644
--- a/apps/docs/content/docs/self-hosted-native.mdx
+++ b/apps/docs/content/docs/self-hosted-native.mdx
@@ -167,4 +167,4 @@ On Windows, stdio MCP commands named npm or npx (including explicit .cmd
paths) run through the selected installation's JavaScript entrypoint with Node.
Other batch wrappers require an explicit cmd.exe command and its arguments.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/self-hosted-native.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/self-hosted-native.md)
diff --git a/apps/docs/content/docs/sessions.mdx b/apps/docs/content/docs/sessions.mdx
index 2e4eb3449..577f29465 100644
--- a/apps/docs/content/docs/sessions.mdx
+++ b/apps/docs/content/docs/sessions.mdx
@@ -34,8 +34,8 @@ leaves the others valid; archiving the Project revokes all its keys. The optiona
## Public resources
Paths are relative to `/v1`. Detailed fields, union types and response shapes are
-in the [public OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/openapi.yaml), fixed SDK source
-and linked semantic records. The [resource inventory](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/README.md#upstream-resource-inventory)
+in the [public OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/openapi.yaml), fixed SDK source
+and linked semantic records. The [resource inventory](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md#upstream-resource-inventory)
lists each operation and its coverage.
| Resource | Route family | Semantics |
@@ -44,11 +44,11 @@ lists each operation and its coverage.
| Sessions and Turns | `/agents/sessions`, nested `/turns` | Admission, metadata, state and recovery queries |
| Items and events | Session `/items`, `/events` | Persisted history and live SSE |
| Artifacts | Session `/artifacts` | Captured output metadata, immutable content and deletion |
-| Subagents | Session `/subagents`, nested `/turns` and `/items` | Scoped child execution reads; [native limits](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/subagents.md) |
-| Environments and workspace Files | `/agents/environments`, nested `/files` | [Environment state](/environments-and-files) and [workspace access](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-files.md) |
-| Environment Templates | `/agents/environments/templates` | [Reusable initialization](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-templates.md) |
-| Source Files | `/files` | [Uploaded content resources](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/source-files.md), distinct from live workspace files |
-| Skills and versions | `/skills`, nested `/versions` | [Bundles and versions](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/file-resource-semantics.md) |
+| Subagents | Session `/subagents`, nested `/turns` and `/items` | Scoped child execution reads; [native limits](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/subagents.md) |
+| Environments and workspace Files | `/agents/environments`, nested `/files` | [Environment state](/environments-and-files) and [workspace access](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-files.md) |
+| Environment Templates | `/agents/environments/templates` | [Reusable initialization](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md) |
+| Source Files | `/files` | [Uploaded content resources](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/source-files.md), distinct from live workspace files |
+| Skills and versions | `/skills`, nested `/versions` | [Bundles and versions](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/file-resource-semantics.md) |
| Vaults and Credentials | `/vaults`, nested `/credentials` | [Scoped write-only credential storage](/environments-and-files) |
SSE is live, not a historical replay service. After a disconnect, query the Session,
@@ -58,14 +58,14 @@ native execution. Do not automatically replay uncertain tool or file effects.
## Core extension fields
The `/v1` route set is exactly the pinned SDK's operations, listed in
-[upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/upstream-routes.json); Core adds
+[upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json); Core adds
no route. It adds fields only inside `x_agents_core`, because it runs several
harnesses and accepts custom model access:
| Field | Where | Reference |
| --- | --- | --- |
-| `x_agents_core.harness` | Saved Agent create, update and read; the inline Session `agent`; the Session's effective `agent` | [Harness selection](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harness-selection.md) |
-| `x_agents_core.model_provider` | Saved Agent create, update and read; Session creation. It takes `protocol`, `base_url`, optional `context_window` and `max_output_tokens`, and a write-only `api_key`; reads return `api_key_configured` instead of the key | [Model execution](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md) |
+| `x_agents_core.harness` | Saved Agent create, update and read; the inline Session `agent`; the Session's effective `agent` | [Harness selection](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-selection.md) |
+| `x_agents_core.model_provider` | Saved Agent create, update and read; Session creation. It takes `protocol`, `base_url`, optional `context_window` and `max_output_tokens`, and a write-only `api_key`; reads return `api_key_configured` instead of the key | [Model execution](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md) |
Any other member of `x_agents_core` is rejected with 400. Deployment, placement,
credential issuance and operational reads are not part of `/v1`; they belong to
@@ -78,7 +78,7 @@ never to `self_hosted`; `none` Sessions accept only the deployment default.
`openai_hosted` and `self_hosted` Sessions must end up with one: otherwise creation
returns 400 with code `model_provider_required` and param
`x_agents_core.model_provider`, and nothing is written. See
-[model execution](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/model-execution.md).
+[model execution](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md).
An application reads a Session's model from `agent.model` and an explicitly
selected harness from `agent.x_agents_core.harness`; a Session on the deployment
@@ -93,8 +93,8 @@ Runtime execution uses the launching user's permissions without an inner sandbox
See [native installation and validation status](/self-hosted-native).
For a `self_hosted` Session, the deployment operator issues the
Environment's executor credential with the Core key; see
-[executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-executor-credentials.md).
+[executor credentials](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-executor-credentials.md).
Our daemon transport and the supported native harness differences are
explicit; they do not imply interoperability with OpenAI's stock executor transport.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/api/public-agent-api.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/api/public-agent-api.md)
diff --git a/apps/docs/content/docs/troubleshooting.mdx b/apps/docs/content/docs/troubleshooting.mdx
index bb292a6c1..0aaf69af8 100644
--- a/apps/docs/content/docs/troubleshooting.mdx
+++ b/apps/docs/content/docs/troubleshooting.mdx
@@ -123,7 +123,7 @@ refuses. `rotate-core-key` refuses to run on a Web-only installation.
## Projects and API keys
Create Projects and issue their keys in Web, on **Projects and keys**, or with the
-[Core API](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md) under `/core/v1/projects`. A key's
+[Core API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) under `/core/v1/projects`. A key's
plaintext is shown once; Core stores only its digest. All keys of a Project share its
assets and execution principal, and each write records the key that made it.
@@ -244,9 +244,9 @@ Core records which key made each public resource write, for the console. Set
`core.write_audit_retention` in `config.json` (Go duration, at least `1h`, default
`2160h`) to control how long non-creation history is kept; creation ownership is kept
for good. Removing keys or resources does not delete these records. See the
-[query contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/write-audit.md); administrator mutations
+[query contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/write-audit.md); administrator mutations
have a separate
-[audit log](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/admin-api.md#monitoring-and-audit). Neither
+[audit log](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md#monitoring-and-audit). Neither
logs bodies or secrets.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/getting-started/operations.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/operations.md)
diff --git a/apps/docs/content/docs/user-guide.mdx b/apps/docs/content/docs/user-guide.mdx
index b6ec176bc..0401114ba 100644
--- a/apps/docs/content/docs/user-guide.mdx
+++ b/apps/docs/content/docs/user-guide.mdx
@@ -13,7 +13,7 @@ Session. For exact request fields, use the [API reference](/public-api).
| --- | --- | --- |
| `openai_hosted` | Ready managed capacity and a configured model | Core creates the Environment and connects its daemon |
| `self_hosted` | Your machine, workspace, daemon and model provider | [Connect the Runtime](/self-hosted-execution) to the returned Environment |
-| `none` | An existing device connection and its configured Harness | Check the qualified profile in [Harness selection](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/harness-selection.md) |
+| `none` | An existing device connection and its configured Harness | Check the qualified profile in [Harness selection](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-selection.md) |
Use the [Environment contract](/environments-and-files) for placement,
expiry and supported combinations. Model selection and provider precedence are
@@ -40,7 +40,7 @@ client.beta.agents.sessions.events.create(
Read the new Turn and Items using the same observation loop as the quickstart.
Submitting while a Turn is active steers that Turn where supported; it does not
create an independent parallel task. Create a new Session for a different fixed
-configuration or workspace. See [message input](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/message-input.md)
+configuration or workspace. See [message input](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md)
for supported content, steering and idempotency rules.
## Prepare Skills, Plugins and MCP
@@ -52,11 +52,11 @@ an existing Session.
| Task | Guide |
| --- | --- |
-| Upload a Skill source and select a version | [Source Files and Skills](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/source-files.md) |
+| Upload a Skill source and select a version | [Source Files and Skills](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/source-files.md) |
| Use local Skill/Plugin directories | [Local capability directories](/self-hosted-execution#local-capability-directories) |
-| Provide initial files, user-directory packages or setup | [Environment Templates](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-templates.md) |
+| Provide initial files, user-directory packages or setup | [Environment Templates](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md) |
| Declare tools, MCP and function callbacks | [Execution tools](/agents-and-tools) |
-| Choose a supported tool policy | [Tool policy](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/tool-policy.md) |
+| Choose a supported tool policy | [Tool policy](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/tool-policy.md) |
System dependencies must already exist on the host or in its image/template.
See the [Runtime installation guide](/self-hosted-native) for dependencies and
@@ -68,14 +68,14 @@ as a new Session to work around an unresolved preparation error.
Turn state tells you whether execution is active, completed, failed or cancelled.
Items hold the recorded conversation and tool results; live events describe changes
as they happen. A disconnected stream is not a completion receipt. The
-[history and events contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/history-events-usage.md) explains
+[history and events contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/history-events-usage.md) explains
pagination, event delivery and Usage.
| Resource | Use it for | Reference |
| --- | --- | --- |
-| Environment Files | Inspect or transfer workspace contents | [Environment Files](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/environment-files.md) |
+| Environment Files | Inspect or transfer workspace contents | [Environment Files](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-files.md) |
| Artifacts | Retrieve captured outputs associated with execution | [Artifacts and public resources](/sessions) |
-| Source Files | Upload input used by a Skill or other declared resource | [Source Files](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/source-files.md) |
+| Source Files | Upload input used by a Skill or other declared resource | [Source Files](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/source-files.md) |
These resources have different lifetimes. Deleting a Session does not erase files
from a user-owned machine. Reclaiming managed compute is a separate Environment
@@ -95,7 +95,7 @@ client.beta.agents.sessions.events.create(
Read the Turn until its terminal state is recorded. HTTP acceptance alone does not
prove native processes have stopped. A cancellation or delivery error must be
interpreted using the returned state and the
-[error contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/core-errors.md).
+[error contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-errors.md).
After a lost response or connection, first retrieve the existing Session, Turns
and Items. Do not assume work was never submitted and send it again. For self-hosted
@@ -111,10 +111,10 @@ A new Session captures a new configuration, not the history of a deleted one.
[supported execution](/agents-and-tools).
4. Follow [operations and troubleshooting](/troubleshooting) for service
logs, credentials and node readiness. Runtime observations may be stale; the
- [diagnostics contract](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/contracts/agents-api/session-diagnostics.md) identifies
+ [diagnostics contract](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/session-diagnostics.md) identifies
which observations are available.
Administrative actions use a different credential from application work. Keep the
[API namespace reference](/public-api) at hand when diagnosing authentication errors.
-[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/e4d5a1d30520a967b3a44a257ed1b6c21e388388/docs/user-guide.md)
+[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/user-guide.md)
diff --git a/apps/docs/content/guide-sources.json b/apps/docs/content/guide-sources.json
index 5c3bbc2f1..1c60f2909 100644
--- a/apps/docs/content/guide-sources.json
+++ b/apps/docs/content/guide-sources.json
@@ -1,15 +1,15 @@
{
- "revision": "e4d5a1d30520a967b3a44a257ed1b6c21e388388",
+ "revision": "f45a4198aca79bf252412c55cad3647f5d704515",
"sources": {
"docs/getting-started/README.md": "cdf8046c616574102a0ffc7644ac0fe82e63eb1906e6c9f1f6b635810e223757",
"docs/design-principles.md": "a33acd6e7bc80105a5c934d0be214c0cff59103e96c098f5b09179c86156c01d",
"docs/web/architecture.md": "80bdb8053c06c2b2030b193aae17d5434545f9c72af50e9d3df3ade522fe25ed",
"docs/getting-started/install.md": "a437b90c2cc4755e0fd760066837bfec96e9aa4a4a4bc5bc865b8ad02162c197",
"docs/getting-started/install-options.md": "aac219f367619036aa01573a295802fb8f0418e3d6db931efcfc88f17cf7734c",
- "docs/configuration.md": "9b18d65f83cc270a937ea4da9aeb6b46645c75635b44a52f3ab1a07f882b440a",
+ "docs/configuration.md": "ca7aa789f6a2a63a493ecf6ebfc083adea94218215e781980cd35ae2aac42298",
"docs/web/core-connection.md": "46f86520e70bf41079708e2c398655aa9087ad9488c8e661d9a73035d11098c4",
"docs/getting-started/quickstart.md": "238b4de1137edb8c2998b38f4525fea345a19fd4de7a455aa9c4c9e4fc3c9b36",
- "docs/api/README.md": "37867a2a1fa5660f343ceed779bf034f2a19a2cd5f516627282c4a87ab68c165",
+ "docs/api/README.md": "628deeb777b7203b42e77a253e91af0f05ca690cd10cb1e08b53b64d62cee923",
"contracts/agents-api/execution-tools.md": "e0b61f6c0c236c362186c5f6d0ad69a16dd8a8d9afabe1329a1fe22e5f4a71e9",
"docs/api/public-agent-api.md": "5b04e5ec9311df851376f66fc1584dd48ca123cd8c26ca63277c10b9172e9955",
"contracts/agents-api/environments.md": "4c4b9423b22919d6aa6bd98d96422e1a8d610d3442d4cf7731a575bd31fd43f0",
@@ -18,41 +18,41 @@
"docs/self-hosted-native.md": "8fc6beccf28ace62e126faa03a923c669298b35213159c5d67b9ac3c7272741b",
"apps/web/public/onboarding/monitor-en.webp": "29dc220cb1250c7016b7c4bf7f30e9510b07c07b814a48c3aa9303b2d76f20b2",
"docs/web/README.md": "9fce295f6f6ff04acefe338679c1e54723e123dd0027a778202adfa9ab95b6c4",
- "docs/api/web-management.md": "d5f982922320069be5017cd524095d86eee0d66fd0d1cf97d1cdd97544d0dce5",
+ "docs/api/web-management.md": "aaae99269518e1fffe02f572d04fdbeb8da5342c309b5016ac31c10a6604dd8e",
"contracts/agents-api/runtime-observability-api.md": "cd46e777fe716a7e76374f4655c96dfbad9d8be1bfca6203ed6118ab87874c2b",
"docs/getting-started/operations.md": "2cba15fe56936cbc51e2ec8b8a888686273b21f729711e45c14ca6e32758663d",
"docs/user-guide.md": "a601c7f9df02c3bfe9c4ca3a43b91ab5721f3f8e904fccd116418dbdc1665a53",
"docs/development.md": "3e03e2666c92380d207ab53285e3b85fdcb042481c8ca76219ed08d629d52812",
- "contracts/agents-api/harness-onboarding.md": "4b491abb0e7b775152752d6669857fb96d2dbfa2bf75333c319a186169b964b0",
+ "contracts/agents-api/harness-onboarding.md": "2c744598f39c156f868418423abdf45d0b52e04b7debaa50ffc95b1b4bb91a87",
"docs/runtime-protocol.md": "6baa332705743e34b8565613d743d1b30099d8af78159b06ad921ffa7e164a9f",
"docs/sandbox-provider.md": "dd8c2c2b2e2acf4d6ae564f56ffaf5685d74a84fa7a7a15b4cad851015ee36ab",
"apps/docs/scripts/guides.json": "109374d4bf1a1d20d10ea85c9400ec6a2f9b62ca0fc6ee6030d3aab94a50d217"
},
"outputs": {
- "content/docs/index.mdx": "f98ce22ef71c0d5921f92b473c465cc27ddbe4616a7606e2138617b9aef4d55f",
- "content/docs/concepts.mdx": "131d926a9efd2446517cb20c3c5d780e2bafda4817d93b1be3ce4a734c3530c5",
- "content/docs/execution-model.mdx": "582e06b1c59fb6fb55da0849db753c6280585e636f68cbb34a812071cd11c4fb",
- "content/docs/install.mdx": "1bd34e90289187eb072753c2f0a3161b7682916e36c90dc4d90400d6ed7ea221",
- "content/docs/install-options.mdx": "8979ba5464db33310a3623d1e9bb8a33f74883e5ec7c4e7412354e62620f247d",
- "content/docs/configure.mdx": "d6eea975362926679173ed7753fece1f0be4ef12368790832f76039888dc0b14",
- "content/docs/bootstrap-projects-keys.mdx": "174d0e61e72e51b08b558fb81fd413f89af58c423435d189d84ba6cb67976d34",
- "content/docs/quickstart.mdx": "c92e0eba73e8725c44062be063e245704de7002e15f92ea0a4eb17498853c171",
- "content/docs/public-api.mdx": "198e171ea4e36695fe346a8226b0371f4b3c4ab7caab46b60c6986a042160194",
- "content/docs/agents-and-tools.mdx": "a3a6a669e25af073bf17cfb9e9699a6fd875dc31cd770fd28c12401078396ae4",
- "content/docs/sessions.mdx": "c4abe10b9115174d10c10c73a373088460276f99f6c2cfe6df6b6aba8d6c7382",
- "content/docs/environments-and-files.mdx": "ce1bab795e30dd4d9d33e5c528fde09f440f9e40aa73fa1461d76e84dfa65008",
- "content/docs/hosted-providers.mdx": "1076b39c59b0b63cc57a92eb738f4b5bd6b842787b16f51f9da0faa3e184ff9b",
- "content/docs/self-hosted-execution.mdx": "f44c344bdc85cbd115b0f80e13e1d811b46364812c1591fee290ca58717bba3f",
- "content/docs/self-hosted-native.mdx": "1f77cf942853d13b9e7be04bde9f9ba072ee8d1b4bcb7d6a05266674c6105df6",
+ "content/docs/index.mdx": "646fb88d73d81fe9a7efa3c066db430d064fcf966c60ecaa94e2a7e8fd18eead",
+ "content/docs/concepts.mdx": "ab0508c9d7c601695148dda6d3f4b709f9366bd4758ad92220f5839c84fcb64e",
+ "content/docs/execution-model.mdx": "6f60226d4f90bc92defb14c5b419d707bb3e419baea781f76eb35c68d3c8ef64",
+ "content/docs/install.mdx": "82f6b7015c2ddfeba16f53004eb6bbf9e5a5499fe97cbeee9b9244ac72ef694d",
+ "content/docs/install-options.mdx": "f21fc20bde39b80f4c6633c65891c73893e5b088b30dbdaed5611ff09656dc97",
+ "content/docs/configure.mdx": "09adaff6510efdd3e24930f00ffef3e39438a858a91bd1e4fb17b344ce709ce2",
+ "content/docs/bootstrap-projects-keys.mdx": "477d76731eb09c14b2c1b09582d595258c1a74cc5b193e92644a340db859e6bd",
+ "content/docs/quickstart.mdx": "0ae6bbd5c488d39489aa2d83bd100e219b9ebb24b86d8dc1489089c197baa775",
+ "content/docs/public-api.mdx": "b2d7cbf9be5d17e9a1a05ddf2f984adad5c14e5703e16e0165619850d6d82131",
+ "content/docs/agents-and-tools.mdx": "9ffa5a5883847f2e4d3641bfd5975baf448fd371542797fd93204f69ea6df5e2",
+ "content/docs/sessions.mdx": "b0e127550c76b26d7649503dcf956044f4236eb798430b1000e356b103b02f1c",
+ "content/docs/environments-and-files.mdx": "2b8a0e0783032ac7e187361cab2225e9fed524f0ae9bacd3edf43804356cd389",
+ "content/docs/hosted-providers.mdx": "4c13986c4512c6b3db1c36b3e383b5760ab6d05349043da71651632ada02120c",
+ "content/docs/self-hosted-execution.mdx": "186b031a0fe04fa6f2196f5df419b37314bb61ad887f36ff404713778b4bb462",
+ "content/docs/self-hosted-native.mdx": "7697ea6535e56a4efbe31cf77bb7df5c0739dc0216eab53e83b5babf90ac1902",
"public/images/source/apps/web/public/onboarding/monitor-en.webp": "29dc220cb1250c7016b7c4bf7f30e9510b07c07b814a48c3aa9303b2d76f20b2",
- "content/docs/console.mdx": "f190022b65fa2ca1ac6dc9cac8e743f63bcbfb6278e8c85b7773f2fc6ca62728",
- "content/docs/admin-api.mdx": "f9711580e69545daae9f364d4d5e246b2a7cf364fb8d8d7691576c63cde0e7b3",
- "content/docs/observability.mdx": "f3edbbd338133c6938bdf42dc3be1938673755bd23f364dd4fa8253b46f06aa8",
- "content/docs/troubleshooting.mdx": "fe75946cb164e2be21fcb0e68bcecddb4688a8385d589ae2b689902d144b0c0b",
- "content/docs/user-guide.mdx": "005b775680b170032fa7f94c6f406f4ceef1d184bb6e58096e38fb6c5be13d43",
- "content/docs/development.mdx": "ae9ac498827cd2ec3eab71277d709de0dd41abb2a5476ba5c976ba76c5dbd791",
- "content/docs/harness-onboarding.mdx": "e35207b97be7d90067b4fd914094d0070fef9ff180dd75b3dba24431f8f4173a",
- "content/docs/runtime-protocol.mdx": "8b7e610cca3350ab744c551f3123d9bc80ea76844a966010e5091c5d96ff849a",
- "content/docs/sandbox-provider.mdx": "f14b45e46ce8a63103c865c6de6859940dad1ced9056405a5e0ee34a63b61f1c"
+ "content/docs/console.mdx": "356769e6017dbb78a9f42ee04d2d50c4bea6fa366a1bf69a062c04e549d63e0f",
+ "content/docs/admin-api.mdx": "d4da5f91b4df53f1ad57e7b71a986a2efc794756a92b76402aff96f480b8a47e",
+ "content/docs/observability.mdx": "595ab9f9918d04c058b64fa3a31d81913bbcbbc4d03138dca63a590979dde112",
+ "content/docs/troubleshooting.mdx": "6447708d4d73f9b7793b00215ddcd000ba411c41606db8987c4d848a64b1cd87",
+ "content/docs/user-guide.mdx": "97194cf016c237f604b7e626297790dc0ea8b570d4e1a866f7395f2813e0e607",
+ "content/docs/development.mdx": "02136ed522b0545dc84fa210cf61d86058e85e1d3acd7890160bd1cce1a13a58",
+ "content/docs/harness-onboarding.mdx": "115c6fcdc640c9260cbdbcb7315630045d1643c86a1b37a4c33a61ecc8053a9a",
+ "content/docs/runtime-protocol.mdx": "59be1013b20c9236ec3480cdc29310e19bd08bbcf2d61d5bee45a9400b43c7be",
+ "content/docs/sandbox-provider.mdx": "3814c84245951b404a786176f7b958d73a7f4548edded55be02be22e143f9880"
}
}
diff --git a/apps/docs/openapi/core-api.yaml b/apps/docs/openapi/core-api.yaml
index 6a0fca892..b14ea33a8 100644
--- a/apps/docs/openapi/core-api.yaml
+++ b/apps/docs/openapi/core-api.yaml
@@ -86,7 +86,7 @@ paths:
- Core Administration
/core/v1/harnesses:
get:
- description: Core key only. Returns every harness this build supports, in name order. enabled and default are read-only views of the process configuration (OAC_DEFAULT_HARNESS and OAC_HARNESSES). model_provider is the harness's deployment default, stored in Core, or null. Keys are never returned; api_key_configured reports that one is set.
+ description: Core key only. Returns every harness this build supports, in name order. enabled and default are read-only views of the process configuration (OAC_DEFAULT_HARNESS and OAC_HARNESSES). model_configuration is the harness's deployment default, stored in Core, or null. Keys are never returned; api_key_configured reports that one is set.
responses:
'200':
description: OK
@@ -111,7 +111,7 @@ paths:
summary: List harnesses and their deployment default model providers
tags:
- Deployment Model Providers
- /core/v1/harnesses/{harness}/model-provider:
+ /core/v1/harnesses/{harness}/model-configuration:
delete:
description: Core key only. Idempotent; each successful request is audited. Sessions that already froze the default keep it. Afterwards new openai_hosted Sessions for this harness need a Session or Agent bundle.
parameters:
@@ -170,7 +170,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/api.HarnessModelProvider'
+ $ref: '#/components/schemas/api.HarnessModelConfiguration'
'401':
description: Unauthorized
content:
@@ -195,7 +195,7 @@ paths:
tags:
- Deployment Model Providers
put:
- description: 'Core key only. The body is the complete x_agents_core.model_provider bundle, including the write-only api_key; there is no partial update and bundles are never merged. The provider is validated for this harness: an HTTPS base_url without credentials, query or fragment, an upstream protocol (responses, anthropic or chat_completions), automatically adapted by Runtime to the selected harness and, for mcode, positive context_window and max_output_tokens. New openai_hosted and none Sessions that resolve no Session or Agent bundle freeze this default into their encrypted snapshot; existing Sessions never change. self_hosted Sessions never use it. The key is encrypted and never returned. Each write records an administrator audit entry without the key and resets last_used_at, last_error_code and last_error_at to null, including identical writes.'
+ description: 'Core key only. The body is the complete x_agents_core.model_configuration bundle, including the write-only api_key; there is no partial update and bundles are never merged. The provider is validated for this harness: an HTTPS base_url without credentials, query or fragment, an upstream protocol (responses, anthropic or chat_completions), automatically adapted by Runtime to the selected harness and, for mcode, positive context_window and max_output_tokens. New openai_hosted and none Sessions resolve omitted model settings from this default and freeze the resolved configuration into their encrypted snapshot; existing Sessions never change. self_hosted Sessions never use it. The key is encrypted and never returned. Each write records an administrator audit entry without the key and resets last_used_at, last_error_code and last_error_at to null, including identical writes.'
parameters:
- schema:
type: string
@@ -213,7 +213,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/api.HarnessModelProvider'
+ $ref: '#/components/schemas/api.HarnessModelConfiguration'
'400':
description: Bad Request
content:
@@ -259,7 +259,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/v1.ModelProviderInput'
+ $ref: '#/components/schemas/v1.ModelConfigurationInput'
description: Complete model provider bundle
required: true
/core/v1/installation:
@@ -4370,11 +4370,13 @@ components:
- codex
- mcode
type: string
- model_provider:
+ model_configuration:
anyOf:
- allOf:
- - $ref: '#/components/schemas/api.HarnessModelProvider'
+ - $ref: '#/components/schemas/api.HarnessModelConfiguration'
- type: 'null'
+ model_configuration_support:
+ $ref: '#/components/schemas/v1.ModelConfigurationSupport'
object:
enum:
- core.harness
@@ -4383,7 +4385,8 @@ components:
- default
- enabled
- id
- - model_provider
+ - model_configuration
+ - model_configuration_support
- object
type: object
api.CoreHarnessList:
@@ -4486,20 +4489,16 @@ components:
- connection
- data
type: object
- api.HarnessModelProvider:
+ api.HarnessModelConfiguration:
properties:
- api_key_configured:
- type: boolean
- base_url:
- type: string
- context_window:
- type: integer
harness:
enum:
- claude_sdk
- codex
- mcode
type: string
+ harness_config:
+ type: object
last_error_at:
anyOf:
- format: date-time
@@ -4524,28 +4523,25 @@ components:
- format: date-time
type: string
- type: 'null'
- max_output_tokens:
- type: integer
- object:
- enum:
- - core.model_provider
+ model:
type: string
- protocol:
+ model_provider:
+ $ref: '#/components/schemas/v1.ModelProviderView'
+ object:
enum:
- - anthropic
- - responses
+ - core.model_configuration
type: string
updated_at:
type: string
required:
- - api_key_configured
- - base_url
- harness
+ - harness_config
- last_error_at
- last_error_code
- last_used_at
+ - model
+ - model_provider
- object
- - protocol
- updated_at
type: object
api.Installation:
@@ -5817,8 +5813,8 @@ components:
- claude_sdk
- mcode
type: string
- required:
- - harness
+ harness_config:
+ type: object
type: object
v1.Credential:
properties:
@@ -6050,6 +6046,21 @@ components:
- has_more
- object
type: object
+ v1.ExecutionHarnessConfigSelection:
+ properties:
+ source:
+ enum:
+ - session
+ - agent
+ - deployment
+ - unknown
+ type: string
+ value:
+ type: object
+ required:
+ - source
+ - value
+ type: object
v1.ExecutionProviderSelection:
properties:
configuration:
@@ -6230,6 +6241,38 @@ components:
- has_more
- object
type: object
+ v1.ModelConfigurationInput:
+ properties:
+ harness_config:
+ type: object
+ model:
+ type: string
+ model_provider:
+ $ref: '#/components/schemas/v1.ModelProviderInput'
+ required:
+ - model
+ - model_provider
+ type: object
+ v1.ModelConfigurationSupport:
+ properties:
+ accepts_harness_config:
+ type: boolean
+ native_protocols:
+ items:
+ type: string
+ type: array
+ protocols:
+ items:
+ type: string
+ type: array
+ token_limits_required:
+ type: boolean
+ required:
+ - accepts_harness_config
+ - native_protocols
+ - protocols
+ - token_limits_required
+ type: object
v1.ModelProviderInput:
properties:
api_key:
@@ -6906,6 +6949,8 @@ components:
- claude_sdk
- mcode
type: string
+ harness_config:
+ type: object
model_provider:
$ref: '#/components/schemas/v1.ModelProviderView'
type: object
@@ -7149,6 +7194,8 @@ components:
properties:
harness:
$ref: '#/components/schemas/v1.ExecutionSelection'
+ harness_config:
+ $ref: '#/components/schemas/v1.ExecutionHarnessConfigSelection'
model:
$ref: '#/components/schemas/v1.ExecutionSelection'
model_provider:
@@ -7165,6 +7212,7 @@ components:
type: string
required:
- harness
+ - harness_config
- model
- model_provider
- object
diff --git a/apps/docs/openapi/public-api.yaml b/apps/docs/openapi/public-api.yaml
index 4b2b205c4..a42d76e65 100644
--- a/apps/docs/openapi/public-api.yaml
+++ b/apps/docs/openapi/public-api.yaml
@@ -3521,8 +3521,8 @@ components:
- claude_sdk
- mcode
type: string
- required:
- - harness
+ harness_config:
+ type: object
type: object
v1.CreateAgentRequest:
properties:
@@ -4668,6 +4668,8 @@ components:
- claude_sdk
- mcode
type: string
+ harness_config:
+ type: object
model_provider:
$ref: '#/components/schemas/v1.ModelProviderView'
type: object
@@ -4679,6 +4681,8 @@ components:
- claude_sdk
- mcode
type: string
+ harness_config:
+ type: object
model_provider:
anyOf:
- allOf:
@@ -5010,6 +5014,8 @@ components:
type: object
v1.SessionExecutionInput:
properties:
+ harness_config:
+ type: object
model_provider:
$ref: '#/components/schemas/v1.ModelProviderInput'
type: object
diff --git a/apps/docs/openapi/sources.json b/apps/docs/openapi/sources.json
index fc1985b82..b095dd873 100644
--- a/apps/docs/openapi/sources.json
+++ b/apps/docs/openapi/sources.json
@@ -1,7 +1,7 @@
{
"sources": {
- "contracts/agents-api/openapi.yaml": "8f569f6b7629ba1d81558b384b985b1dd7598365c162bd27cb8d65a31cb5b83e",
- "contracts/agents-api/core.openapi.yaml": "f036df1154a7fd29a900291c06345754dc3d30c6d04a0f8e23a3f673fce1d51f",
+ "contracts/agents-api/openapi.yaml": "b706abf259542b7b9a833b566f20048412d3cbc27c4c4284ed6baf5edc605489",
+ "contracts/agents-api/core.openapi.yaml": "3074ec8de0e313ec116487e96f6b27ac1aa1597f95db4bb162c73ce4d1c184e2",
"contracts/agents-api/runtime.openapi.yaml": "505286d5eacf94a14f9527fcf4e7beb4fba4f792681be26ba966254cbf49b4aa"
},
"outputs": {
@@ -18,11 +18,11 @@
"content/docs/api-reference/skills.mdx": "774ea05a7a8250fe5af5164388b98dafca99d56dc2eae686e8f628acb4e7c10b",
"content/docs/api-reference/vaults.mdx": "d80eade1c2f8100030866abbb0fb6b7a09c94250a859c97cdf1abce32fdfdf1e",
"content/docs/api-reference/credentials.mdx": "f129a51f74a3c7021c016600518e2350023f8d29571666ac5d64b7584cd7c7d0",
- "openapi/public-api.yaml": "f9a5955085f075b9bbd81be58a0e37ded8fd9c3ea32275e6ec43676c2f417f78",
+ "openapi/public-api.yaml": "a546a465b7e8e0206a0b60f28533a1ee78f21417c7b54bcdb6e98d7b3638d940",
"content/docs/api-reference/meta.json": "56bf1dc145ccc8adde38c5f956f1a06f18ef18b646122250d01a294c516f8f83",
"content/docs/api-reference/index.mdx": "9fd6b1c54149874d2999235067c101326f9e8a2e707a70b6672c81eb3ebfe63f",
"content/docs/api-reference/core/core-administration.mdx": "5fc3ada51d2190a141f13738151e4d513390cc3bd66ce6f5013994bda68569b0",
- "content/docs/api-reference/core/deployment-model-providers.mdx": "0bec8760bc1e0dd9badf36bfab90f8f5593e3614761c2d082c4fcf46ab3aefd2",
+ "content/docs/api-reference/core/deployment-model-providers.mdx": "bf207c1f14f1ce0a9efaa778cdb8ae77b5cc932ec25cc264f3f3dc08d4ce0591",
"content/docs/api-reference/core/administrator-projects.mdx": "8fd687bb2a7119fa16e938d7c71710c2816afb9cf959eb6849ef5e6300c5419b",
"content/docs/api-reference/core/agents.mdx": "b6c089fbea4b07bc4249e7c7ca5699d47f1512a4fc2d8ee01cb26910ae541a84",
"content/docs/api-reference/core/environment-templates.mdx": "05907f35d7f02d66af9da8b1efaa3765badb4cdf7b94d0f6c3ab0413a2cfa1a9",
@@ -41,7 +41,7 @@
"content/docs/api-reference/core/vaults.mdx": "12d0aac96cd4a3472ef4eaa287f7945f78862017956e79bfc3ed0ef8e772e78a",
"content/docs/api-reference/core/credentials.mdx": "27d586b9a8fd738b9947802f32c80458195370252886bc26abedccf2125ee981",
"content/docs/api-reference/core/sandbox-manager.mdx": "6be7c52e057365949f0247c18c710561d680847a955f78f1bbe57825d4d5f549",
- "openapi/core-api.yaml": "326da8a30dc26633d73b2d769e53ab131c0b897cd89c449e941bbc4cfc814406",
+ "openapi/core-api.yaml": "a3eb0ad9a86144576ed625a9dc1abcba924c00c7b081bf193cfdf1ea5b58f68a",
"content/docs/api-reference/core/meta.json": "d0aef1f54c4cfc30b4e1d974119ae1cdce1c87d5ecba723afbeb4599119482a7",
"content/docs/api-reference/core/index.mdx": "57cf9ea947ef45e79575c25a0a3d4e5e856dde6d14698ccc2c51b86201c249e9",
"content/docs/api-reference/machine/native-installation.mdx": "421a858685b79fdcf8d7eff308c5768d1b62385c3988c6089f380afe80aaed69",
diff --git a/apps/docs/scripts/generate-guides.mjs b/apps/docs/scripts/generate-guides.mjs
index db4a9eee7..e401e5913 100644
--- a/apps/docs/scripts/generate-guides.mjs
+++ b/apps/docs/scripts/generate-guides.mjs
@@ -8,7 +8,7 @@ const app = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
const repo = path.resolve(app, '../..')
const guides = JSON.parse(fs.readFileSync(path.join(app, 'scripts/guides.json'), 'utf8'))
const routes = new Map(guides.map(g => [g.source, g.slug === 'index' ? '/' : '/' + g.slug]))
-const sourceRevision = 'e4d5a1d30520a967b3a44a257ed1b6c21e388388'
+const sourceRevision = 'f45a4198aca79bf252412c55cad3647f5d704515'
const sourceURL = relative => `https://github.com/MiniMax-AI/parsar-core/blob/${sourceRevision}/${relative}`
const digest = text => crypto.createHash('sha256').update(text).digest('hex')
function mdx(text) {
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/executor.go b/apps/parsar-daemon/internal/agent/claudesdk/executor.go
index e506b30d0..a8ba4b561 100644
--- a/apps/parsar-daemon/internal/agent/claudesdk/executor.go
+++ b/apps/parsar-daemon/internal/agent/claudesdk/executor.go
@@ -12,10 +12,12 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ harnessconfiguration "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig/claudesdk"
"github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
)
type executor struct {
+ modelRoute modeltransport.Route
modelEndpoint *modeltransport.Endpoint
mu sync.Mutex
base *session
@@ -41,7 +43,7 @@ func NewExecutorFactory(config Config) agent.ExecutorFactory {
if req.RunID != "" || len(req.Input) != 0 || req.ConversationID != "" {
return nil, errors.New("claudesdk: Executor preparation cannot submit input")
}
- options, endpoint, err := modeltransport.PrepareOptions(req.AgentOptions, modeltransport.Anthropic)
+ options, endpoint, err := modeltransport.PrepareRequestOptions(req, harnessconfiguration.Configuration().NativeProtocols()...)
if err != nil {
return nil, err
}
@@ -71,6 +73,9 @@ func NewExecutorFactory(config Config) agent.ExecutorFactory {
base.reads.supported = slices.Contains(info.Features, "workspace_read")
base.directories.supported = slices.Contains(info.Features, "workspace_directory")
e := &executor{modelEndpoint: endpoint, base: base, start: start, ready: make(chan error, 1), done: make(chan struct{}), nativeID: start.Resume}
+ if endpoint != nil {
+ e.modelRoute = endpoint.Route
+ }
transferred = true
go e.read()
if err = e.write(start); err == nil {
@@ -203,12 +208,15 @@ func (e *executor) StartTurn(ctx context.Context, run string, input proto.Messag
if strings.TrimSpace(run) == "" || input.Validate() != nil || out == nil || ctx.Err() != nil {
return nil, errors.New("claudesdk: Turn requires live context, identity, input and output")
}
+ if err := e.modelRoute.ValidateInput(input); err != nil {
+ return nil, err
+ }
e.mu.Lock()
if e.invalid || e.active != nil || e.base.process.Context().Err() != nil {
e.mu.Unlock()
return nil, errors.New("claudesdk: Executor is unavailable")
}
- s := &session{owner: e, runID: run, process: e.base.process, writeMu: e.base.writeMu, frames: make(chan []byte, 64), functions: functionState{calls: map[string]*pendingFunction{}}, settled: make(chan struct{}), outputDone: make(chan struct{}), cancelOutput: make(chan struct{})}
+ s := &session{modelRoute: e.modelRoute, owner: e, runID: run, process: e.base.process, writeMu: e.base.writeMu, frames: make(chan []byte, 64), functions: functionState{calls: map[string]*pendingFunction{}}, settled: make(chan struct{}), outputDone: make(chan struct{}), cancelOutput: make(chan struct{})}
start := e.start
start.Resume = e.nativeID
e.active = s
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/functions.go b/apps/parsar-daemon/internal/agent/claudesdk/functions.go
index aaa56e61c..89d3e56ca 100644
--- a/apps/parsar-daemon/internal/agent/claudesdk/functions.go
+++ b/apps/parsar-daemon/internal/agent/claudesdk/functions.go
@@ -100,6 +100,9 @@ func (s *session) receiveFunction(event bridgeEvent, start startRequest, emit fu
}
func (s *session) SubmitFunctionResult(ctx context.Context, result proto.FunctionResultPayload) error {
+ if err := s.modelRoute.ValidateFunctionResult(result); err != nil {
+ return err
+ }
if result.CallID == "" || result.DeliveryID == "" {
return fmt.Errorf("claudesdk: function result identities are required")
}
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/harness_config_test.go b/apps/parsar-daemon/internal/agent/claudesdk/harness_config_test.go
new file mode 100644
index 000000000..98e9baf54
--- /dev/null
+++ b/apps/parsar-daemon/internal/agent/claudesdk/harness_config_test.go
@@ -0,0 +1,38 @@
+package claudesdk
+
+import (
+ "encoding/json"
+ "github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig"
+ "path/filepath"
+ "testing"
+)
+
+func TestHarnessConfigReachesBridgeAndOwnsSnapshot(t *testing.T) {
+ root := t.TempDir()
+ t.Setenv("OAC_RUNTIME_HOME", root)
+ config := Config{Entrypoint: filepath.Join(root, "main.js"), StateDir: filepath.Join(root, "state")}
+ native := map[string]any{"effort": "high", "thinking": map[string]any{"type": "enabled", "budgetTokens": 1024}}
+ req := proto.PromptRequestPayload{AgentOptions: map[string]any{"model": "fixture", "harness_config": native}}
+ start, _, err := prepareConfiguration(config, req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ native["thinking"].(map[string]any)["budgetTokens"] = 2048
+ raw, err := json.Marshal(start)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var bridge map[string]any
+ if json.Unmarshal(raw, &bridge) != nil {
+ t.Fatal("invalid bridge request")
+ }
+ applied := bridge["harness_config"].(map[string]any)
+ if applied["effort"] != "high" || applied["thinking"].(map[string]any)["budgetTokens"] != float64(1024) {
+ t.Fatal("bridge lost immutable native configuration")
+ }
+ req.AgentOptions["harness_config"] = map[string]any{"env": map[string]any{"ANTHROPIC_BASE_URL": "bypass"}}
+ if _, _, err = prepareConfiguration(config, req); err != harnessconfig.ErrHarnessConfig {
+ t.Fatalf("provider override accepted: %v", err)
+ }
+}
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/model_route_test.go b/apps/parsar-daemon/internal/agent/claudesdk/model_route_test.go
new file mode 100644
index 000000000..37d9a112e
--- /dev/null
+++ b/apps/parsar-daemon/internal/agent/claudesdk/model_route_test.go
@@ -0,0 +1,49 @@
+//go:build unix
+
+package claudesdk
+
+import (
+ "testing"
+
+ "github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
+)
+
+func TestConvertedExecutorRejectsFutureImages(t *testing.T) {
+ config, req := persistentConfig(t, "complete")
+ req.AgentOptions["model_provider"] = map[string]any{"protocol": "chat_completions", "base_url": "https://model.invalid/v1", "api_key": "private-sentinel"}
+ resource, err := NewExecutorFactory(config)(t.Context(), req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer resource.Close(t.Context())
+ e := resource.(*executor)
+ if !e.modelRoute.Converted() {
+ t.Fatal("conversion route was not retained")
+ }
+ out := make(chan proto.Envelope, 20)
+ turn, err := e.StartTurn(t.Context(), "text-first", proto.TextInput("hello"), out)
+ if err != nil {
+ t.Fatal(err)
+ }
+ settlement, err := turn.AwaitSettlement(t.Context())
+ if err != nil || !settlement.Reusable {
+ t.Fatalf("text did not settle: %v", err)
+ }
+ for range out {
+ }
+ ref := "data:image/png;base64,AA=="
+ input := proto.MessageInput{{Content: []proto.InputContent{{Type: "input_image", ImageURL: &ref}}}}
+ out = make(chan proto.Envelope, 20)
+ if next, err := e.StartTurn(t.Context(), "image-next", input, out); next != nil || err != modeltransport.ErrUnsupported {
+ t.Fatalf("image acquired native ownership: %v", err)
+ }
+ s := turn.(*session)
+ if err := s.SteerWithReceipt(t.Context(), proto.PromptSteerPayload{InputID: "image", Input: input}, nil); err != modeltransport.ErrUnsupported {
+ t.Fatalf("steer accepted image: %v", err)
+ }
+ if err := s.SubmitFunctionResult(t.Context(), proto.FunctionResultPayload{CallID: "call", DeliveryID: "delivery", Success: true, Content: input[0].Content}); err != modeltransport.ErrUnsupported {
+ t.Fatalf("tool image accepted: %v", err)
+ }
+ close(out)
+}
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/options.go b/apps/parsar-daemon/internal/agent/claudesdk/options.go
index 36822c5f7..4afdb4453 100644
--- a/apps/parsar-daemon/internal/agent/claudesdk/options.go
+++ b/apps/parsar-daemon/internal/agent/claudesdk/options.go
@@ -8,6 +8,7 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/paths"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ harnessconfiguration "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig/claudesdk"
)
type Config struct {
@@ -23,6 +24,7 @@ type subagentOptions struct {
}
type startRequest struct {
+ HarnessConfig proto.HarnessConfig `json:"harness_config,omitempty"`
ToolSearch bool `json:"tool_search,omitempty"`
Subagents *subagentOptions `json:"subagents,omitempty"`
OutputFormat *proto.OutputFormat `json:"output_format,omitempty"`
@@ -57,6 +59,11 @@ func prepareConfiguration(config Config, req proto.PromptRequestPayload) (startR
fail := func(reason string) (startRequest, []string, error) {
return startRequest{}, nil, fmt.Errorf("claudesdk: %s", reason)
}
+ nativeConfig, err := harnessconfiguration.Configuration().PrepareHarnessConfig(req.AgentOptions)
+ if err != nil {
+ return startRequest{}, nil, err
+ }
+ start.HarnessConfig = nativeConfig
if req.WorkspaceAuthoring || req.ObserveTools {
return fail("requested capability is not available in the private SDK adapter")
}
@@ -105,6 +112,9 @@ func prepareConfiguration(config Config, req proto.PromptRequestPayload) (startR
}
var provider []string
for name, raw := range req.AgentOptions {
+ if name == "harness_config" {
+ continue
+ }
if name == "model_provider" {
var err error
provider, err = providerEnvironment(raw)
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/session.go b/apps/parsar-daemon/internal/agent/claudesdk/session.go
index f8d7a1f82..a70dc3c48 100644
--- a/apps/parsar-daemon/internal/agent/claudesdk/session.go
+++ b/apps/parsar-daemon/internal/agent/claudesdk/session.go
@@ -9,9 +9,11 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent"
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent/clirunner"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
)
type session struct {
+ modelRoute modeltransport.Route
owner *executor
runID string
frames chan []byte
diff --git a/apps/parsar-daemon/internal/agent/claudesdk/steering.go b/apps/parsar-daemon/internal/agent/claudesdk/steering.go
index c9d2c0eae..1485ada3d 100644
--- a/apps/parsar-daemon/internal/agent/claudesdk/steering.go
+++ b/apps/parsar-daemon/internal/agent/claudesdk/steering.go
@@ -34,6 +34,9 @@ func (s *session) Steer(ctx context.Context, input proto.PromptSteerPayload) err
// SteerWithReceipt separates a complete bridge write from native consumption.
func (s *session) SteerWithReceipt(ctx context.Context, input proto.PromptSteerPayload, written func()) error {
+ if err := s.modelRoute.ValidateInput(input.Input); err != nil {
+ return err
+ }
select {
case <-s.cancelOutput:
return agent.ErrSteeringInactive
diff --git a/apps/parsar-daemon/internal/agent/codex/executor.go b/apps/parsar-daemon/internal/agent/codex/executor.go
index b64ba3756..09babe5e2 100644
--- a/apps/parsar-daemon/internal/agent/codex/executor.go
+++ b/apps/parsar-daemon/internal/agent/codex/executor.go
@@ -44,6 +44,9 @@ func (e *Executor) StartTurn(ctx context.Context, runID string, input proto.Mess
if out == nil || strings.TrimSpace(runID) == "" || input.Validate() != nil {
return nil, errors.New("codex: start requires a run identity, input and output")
}
+ if err := e.prepared.plan.ModelRoute.ValidateInput(input); err != nil {
+ return nil, err
+ }
if err := ctx.Err(); err != nil {
return nil, err
}
@@ -68,7 +71,7 @@ func (e *Executor) StartTurn(ctx context.Context, runID string, input proto.Mess
}
functions := &functionCalls{definitions: base.functions.definitions, names: base.functions.names, pending: map[string]*pendingFunction{}}
turnCtx, cancel := context.WithCancel(base.cancelCtx)
- s := &Session{executor: e, nativeHome: base.nativeHome,
+ s := &Session{modelRoute: base.modelRoute, executor: e, nativeHome: base.nativeHome,
functions: functions, observeMessages: base.observeMessages, observeTools: base.observeTools,
observeToolObservations: base.observeToolObservations, observeSubagentIdentities: base.observeSubagentIdentities,
cfg: base.cfg, rpc: base.rpc, cancelCtx: turnCtx, cancelFn: cancel,
diff --git a/apps/parsar-daemon/internal/agent/codex/function_receipts.go b/apps/parsar-daemon/internal/agent/codex/function_receipts.go
index 8c594209d..9e80aa71e 100644
--- a/apps/parsar-daemon/internal/agent/codex/function_receipts.go
+++ b/apps/parsar-daemon/internal/agent/codex/function_receipts.go
@@ -26,6 +26,9 @@ type pendingFunction struct {
}
func (s *Session) SubmitFunctionResult(ctx context.Context, result proto.FunctionResultPayload) error {
+ if err := s.modelRoute.ValidateFunctionResult(result); err != nil {
+ return err
+ }
if !s.beginOperation() {
return agent.ErrSteeringInactive
}
diff --git a/apps/parsar-daemon/internal/agent/codex/harness_config_test.go b/apps/parsar-daemon/internal/agent/codex/harness_config_test.go
new file mode 100644
index 000000000..42574bd3e
--- /dev/null
+++ b/apps/parsar-daemon/internal/agent/codex/harness_config_test.go
@@ -0,0 +1,92 @@
+package codex
+
+import (
+ "context"
+ "encoding/json"
+ "time"
+
+ "github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig"
+ "slices"
+ "testing"
+)
+
+func TestHarnessConfigAppliedWithoutChangingProvider(t *testing.T) {
+ t.Setenv("OAC_RUNTIME_HOME", t.TempDir())
+ plan, err := BuildSessionPlan("run", "native-config", "", map[string]any{
+ "model": "fixture", "harness_config": map[string]any{"model_reasoning_effort": "high"},
+ "model_provider": map[string]any{"base_url": "https://provider.invalid/v1", "protocol": "responses", "api_key": "test-key"},
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer plan.Cleanup()
+ if plan.Model != "fixture" || plan.ModelProvider != oacProviderSlug || !slices.Contains(plan.ExtraConfig, [2]string{"model_reasoning_effort", `"high"`}) {
+ t.Fatalf("native configuration not applied: %+v", plan.ExtraConfig)
+ }
+}
+
+func TestHarnessConfigConflictFailsBeforePreparation(t *testing.T) {
+ _, err := BuildSessionPlan("run", "", "", map[string]any{"harness_config": map[string]any{"model_provider": "bypass"}})
+ if err != harnessconfig.ErrHarnessConfig {
+ t.Fatalf("configuration must fail before filesystem preparation: %v", err)
+ }
+}
+
+func TestHarnessConfigReachesEveryNativeTurn(t *testing.T) {
+ for _, resumeID := range []string{"", "fixture-native-thread"} {
+ t.Run("resume="+resumeID, func(t *testing.T) {
+ req, cfg, root := preparationFixture(t)
+ t.Setenv("OAC_TEST_EXECUTOR_MODE", "complete")
+ req.AgentSessionID = resumeID
+ native := map[string]any{"model_reasoning_effort": "high"}
+ req.AgentOptions["harness_config"] = native
+ ownerCtx, cancelOwner := context.WithCancel(context.Background())
+ t.Cleanup(cancelOwner)
+ e, err := newExecutor(ownerCtx, req, cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Cleanup(func() {
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ if err := e.Close(ctx); err != nil {
+ t.Error(err)
+ }
+ })
+ native["model_reasoning_effort"] = "low"
+ for _, id := range []string{"one", "two"} {
+ out := make(chan proto.Envelope, 20)
+ turn, err := e.StartTurn(t.Context(), id, proto.TextInput("answer"), out)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !awaitExecutorTurn(t, turn, out).Reusable {
+ t.Fatal("healthy Turn was not reusable")
+ }
+ }
+ counts := map[string]int{}
+ for _, frame := range preparationFrames(t, root) {
+ counts[frame.Method]++
+ if frame.Method != "turn/start" {
+ continue
+ }
+ var wire struct {
+ CollaborationMode struct {
+ Settings map[string]any `json:"settings"`
+ } `json:"collaborationMode"`
+ }
+ if json.Unmarshal(frame.Params, &wire) != nil || wire.CollaborationMode.Settings["reasoning_effort"] != "high" {
+ t.Fatal("Turn lost the frozen native reasoning effort", string(frame.Params))
+ }
+ }
+ method := "thread/start"
+ if resumeID != "" {
+ method = "thread/resume"
+ }
+ if counts[method] != 1 || counts["turn/start"] != 2 {
+ t.Fatal("expected one native thread and two Turns", counts)
+ }
+ })
+ }
+}
diff --git a/apps/parsar-daemon/internal/agent/codex/model_route_test.go b/apps/parsar-daemon/internal/agent/codex/model_route_test.go
new file mode 100644
index 000000000..7ed091b60
--- /dev/null
+++ b/apps/parsar-daemon/internal/agent/codex/model_route_test.go
@@ -0,0 +1,41 @@
+package codex
+
+import (
+ "testing"
+
+ "github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
+)
+
+func TestConvertedExecutorRejectsFutureImageBeforeOwnership(t *testing.T) {
+ e, root := executorFixture(t, "complete")
+ route := modeltransport.Route{Native: modeltransport.Responses, Upstream: modeltransport.Anthropic}
+ e.prepared.plan.ModelRoute = route
+ e.prepared.session.modelRoute = route
+ out := make(chan proto.Envelope, 20)
+ turn, err := e.StartTurn(t.Context(), "text-first", proto.TextInput("hello"), out)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !awaitExecutorTurn(t, turn, out).Reusable {
+ t.Fatal("text did not settle")
+ }
+ before := len(preparationFrames(t, root))
+ ref := "data:image/png;base64,AA=="
+ input := proto.MessageInput{{Content: []proto.InputContent{{Type: "input_image", ImageURL: &ref}}}}
+ out = make(chan proto.Envelope, 20)
+ if next, err := e.StartTurn(t.Context(), "image-next", input, out); next != nil || err != modeltransport.ErrUnsupported {
+ t.Fatalf("image acquired output/native ownership: %v", err)
+ }
+ session := turn.(*Session)
+ if err := session.SteerWithReceipt(t.Context(), proto.PromptSteerPayload{InputID: "image", Input: input}, nil); err != modeltransport.ErrUnsupported {
+ t.Fatalf("steer accepted image: %v", err)
+ }
+ if err := session.SubmitFunctionResult(t.Context(), proto.FunctionResultPayload{CallID: "call", DeliveryID: "delivery", Success: true, Content: input[0].Content}); err != modeltransport.ErrUnsupported {
+ t.Fatalf("tool image accepted: %v", err)
+ }
+ if len(preparationFrames(t, root)) != before {
+ t.Fatal("rejected content reached native process")
+ }
+ close(out)
+}
diff --git a/apps/parsar-daemon/internal/agent/codex/options.go b/apps/parsar-daemon/internal/agent/codex/options.go
index 5b8418149..e27e727fc 100644
--- a/apps/parsar-daemon/internal/agent/codex/options.go
+++ b/apps/parsar-daemon/internal/agent/codex/options.go
@@ -10,12 +10,14 @@ import (
"strings"
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/paths"
+ harnessconfiguration "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig/codex"
"github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
)
// SessionPlan holds the resolved per-prompt launch plan derived from
// the daemon's PromptRequestPayload.
type SessionPlan struct {
+ ModelRoute modeltransport.Route
// Cwd is the validated working directory passed to codex (and to
// the spawned app-server). Empty when the caller provided no work_dir.
@@ -57,6 +59,9 @@ type SessionPlan struct {
// CollaborationMode selects Codex's default or plan tool surface.
CollaborationMode CollaborationModeKind
+ // ModelReasoningEffort is frozen for launch and every native Turn.
+ ModelReasoningEffort string
+
// ApprovalPolicy + Sandbox apply to both new and resumed threads.
ApprovalPolicy AskForApproval
Sandbox SandboxMode
@@ -101,6 +106,11 @@ func BuildSessionPlan(runID, agentStateKey, workDir string, opts map[string]any)
Cleanup: cleanup,
}
+ nativeConfig, err := harnessconfiguration.Configuration().PrepareHarnessConfig(opts)
+ if err != nil {
+ return plan, err
+ }
+
if value, present := opts["web_search"]; present {
switch value {
case "disabled", "cached", "live":
@@ -166,11 +176,12 @@ func BuildSessionPlan(runID, agentStateKey, workDir string, opts map[string]any)
}
// The native adapter selects Responses; Runtime converts other upstream protocols.
- preparedOptions, endpoint, err := modeltransport.PrepareOptions(opts, modeltransport.Responses)
+ preparedOptions, endpoint, err := modeltransport.PrepareOptions(opts, harnessconfiguration.Configuration().NativeProtocols()...)
if err != nil {
return plan, err
}
if endpoint != nil {
+ plan.ModelRoute = endpoint.Route
cleanup = func() { _ = endpoint.Close() }
plan.Cleanup = cleanup
}
@@ -190,6 +201,10 @@ func BuildSessionPlan(runID, agentStateKey, workDir string, opts map[string]any)
plan.Env = env
plan.Cleanup = cleanup
plan.ExtraConfig = extraConfigFromOpts(opts)
+ if effort, ok := nativeConfig["model_reasoning_effort"].(string); ok {
+ plan.ModelReasoningEffort = effort
+ plan.ExtraConfig = append(plan.ExtraConfig, [2]string{"model_reasoning_effort", strconv(effort)})
+ }
if plan.ModelProvider != "" {
// Pin model_provider at the CLI layer so codex skips its builtin
// "openai" provider — without this the [model_providers.oac]
diff --git a/apps/parsar-daemon/internal/agent/codex/preparation.go b/apps/parsar-daemon/internal/agent/codex/preparation.go
index 5f7578418..09641664e 100644
--- a/apps/parsar-daemon/internal/agent/codex/preparation.go
+++ b/apps/parsar-daemon/internal/agent/codex/preparation.go
@@ -87,6 +87,7 @@ func newPreparation(parent context.Context, req proto.PromptRequestPayload, cfg
rpc := NewJSONRPCClient(rpcCfg)
s := &Session{
+ modelRoute: plan.ModelRoute,
nativeHome: nativeHomeFromPlan(plan),
functions: functions,
observeMessages: req.ObserveMessages,
diff --git a/apps/parsar-daemon/internal/agent/codex/prepared.go b/apps/parsar-daemon/internal/agent/codex/prepared.go
index b4e3a0b78..88c5d142e 100644
--- a/apps/parsar-daemon/internal/agent/codex/prepared.go
+++ b/apps/parsar-daemon/internal/agent/codex/prepared.go
@@ -42,6 +42,9 @@ func (p *Prepared) start(ctx context.Context, runID string, prompt proto.Message
if out == nil || strings.TrimSpace(runID) == "" || prompt.Validate() != nil {
return nil, errors.New("codex: start requires a run identity, prompt and output channel")
}
+ if err := p.plan.ModelRoute.ValidateInput(prompt); err != nil {
+ return nil, err
+ }
p.mu.Lock()
if p.claimed || p.closed {
p.mu.Unlock()
diff --git a/apps/parsar-daemon/internal/agent/codex/protocol.go b/apps/parsar-daemon/internal/agent/codex/protocol.go
index a5f91baf5..81a1d9b93 100644
--- a/apps/parsar-daemon/internal/agent/codex/protocol.go
+++ b/apps/parsar-daemon/internal/agent/codex/protocol.go
@@ -249,6 +249,7 @@ type CollaborationMode struct {
}
type CollaborationModeSettings struct {
+ ReasoningEffort string `json:"reasoning_effort,omitempty"`
Model string `json:"model"`
DeveloperInstructions *string `json:"developer_instructions"`
}
diff --git a/apps/parsar-daemon/internal/agent/codex/session.go b/apps/parsar-daemon/internal/agent/codex/session.go
index f53a49261..be6b076fb 100644
--- a/apps/parsar-daemon/internal/agent/codex/session.go
+++ b/apps/parsar-daemon/internal/agent/codex/session.go
@@ -12,6 +12,7 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
obslog "github.com/MiniMax-AI-Dev/parsar/internal/obs/log"
)
@@ -54,6 +55,7 @@ func Factory(ctx context.Context, req proto.PromptRequestPayload, out chan<- pro
// 5. turn/completed emits TypeDone + closes out. Cancel can short-cut
// this by killing the child early.
type Session struct {
+ modelRoute modeltransport.Route
retiredTurns map[string]bool
executor *Executor
outputDone chan struct{}
diff --git a/apps/parsar-daemon/internal/agent/codex/session_plan.go b/apps/parsar-daemon/internal/agent/codex/session_plan.go
index 4dad48a69..351d75852 100644
--- a/apps/parsar-daemon/internal/agent/codex/session_plan.go
+++ b/apps/parsar-daemon/internal/agent/codex/session_plan.go
@@ -7,6 +7,7 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/localworkspace"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
)
func prepareSessionPlan(ctx context.Context, req proto.PromptRequestPayload, cfg sessionConfig) (SessionPlan, []string, error) {
@@ -25,6 +26,10 @@ func prepareSessionPlan(ctx context.Context, req proto.PromptRequestPayload, cfg
if err != nil {
return SessionPlan{}, nil, fmt.Errorf("codex: build session plan: %w", err)
}
+ if err := plan.ModelRoute.Validate(modeltransport.RequirementsFromRequest(req)); err != nil {
+ plan.Cleanup()
+ return SessionPlan{}, nil, err
+ }
if err := configureSubagentObservations(&plan, req); err != nil {
plan.Cleanup()
return SessionPlan{}, nil, err
diff --git a/apps/parsar-daemon/internal/agent/codex/session_run.go b/apps/parsar-daemon/internal/agent/codex/session_run.go
index 21736ba88..a482b8585 100644
--- a/apps/parsar-daemon/internal/agent/codex/session_run.go
+++ b/apps/parsar-daemon/internal/agent/codex/session_run.go
@@ -59,6 +59,7 @@ func (s *Session) startNative(ctx context.Context, plan SessionPlan, req proto.P
turnParams.CollaborationMode = &CollaborationMode{
Mode: plan.CollaborationMode,
Settings: CollaborationModeSettings{
+ ReasoningEffort: plan.ModelReasoningEffort,
Model: model,
DeveloperInstructions: developerInstructions,
},
diff --git a/apps/parsar-daemon/internal/agent/codex/session_steering.go b/apps/parsar-daemon/internal/agent/codex/session_steering.go
index f0d6be931..a27391b4a 100644
--- a/apps/parsar-daemon/internal/agent/codex/session_steering.go
+++ b/apps/parsar-daemon/internal/agent/codex/session_steering.go
@@ -38,6 +38,9 @@ func (s *Session) SteerWithReceipt(ctx context.Context, input proto.PromptSteerP
}
func (s *Session) steer(ctx context.Context, input proto.PromptSteerPayload, written func()) error {
+ if err := s.modelRoute.ValidateInput(input.Input); err != nil {
+ return err
+ }
if !s.beginOperation() {
return agent.ErrSteeringInactive
}
diff --git a/apps/parsar-daemon/internal/agent/harness.go b/apps/parsar-daemon/internal/agent/harness.go
index 664115aba..034d0c8a2 100644
--- a/apps/parsar-daemon/internal/agent/harness.go
+++ b/apps/parsar-daemon/internal/agent/harness.go
@@ -29,6 +29,54 @@ import (
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
)
+// ExecutorFactory must prepare model configuration before native startup and
+// before submitting model input; accepted fields must never be silently dropped.
+// proto.HarnessConfig is a JSON object: omission and {} are empty configuration;
+// explicit null, arrays and objects above 16 KiB of serialized UTF-8 bytes are
+// invalid. The selected
+// adapter owns field names, meanings and native validation. See the native model
+// configuration section of contracts/agents-api/harness-onboarding.md.
+// Core freezes model, model_provider and proto.HarnessConfig in the Session.
+// Runtime resolves modeltransport first; adapters consume only its final effective
+// connection (address, protocol and authentication).
+// Each adapter declares safe native model fields in internal/harnessconfig and
+// validates the same declaration at admission and again before native application.
+// Unknown fields and conflicts with model, provider/authentication, workspace,
+// tools/MCP, permissions or lifecycle controls fail with a value-free error.
+// Apply accepted fields directly to native config or SDK options, without a
+// cross-Harness parameter translation layer. Never merge arbitrary host config.
+// Preparation failure cleans up owned configuration files, processes/SDK resources
+// and proxies. Unconfirmed cleanup returns a non-nil Executor with the error under
+// the factory ownership contract. The logical configuration snapshot remains fixed
+// across Turns and reconnects; rebuilding an Executor may regenerate local proxy
+// addresses or short-lived credentials. Configuration defaults and inheritance
+// belong to the public API contract.
+
+// Configuration support is declared once by each adapter in internal/harnessconfig:
+// accepted upstream protocols, native protocols, token-limit requirements and its
+// native model-parameter validator. Core admission, Runtime and modeltransport
+// consume that declaration; adding a Harness must not introduce another public
+// configuration shape or a Harness-name branch in orchestration.
+//
+// modeltransport owns route selection and preservation requirements. JSON parsing,
+// adapter acceptance, conversion qualification and upstream model support are
+// separate facts. A registered translator alone does not prove preservation.
+// Native routes keep the original protocol; conversion routes must reject an
+// unqualified requirement before forwarding model input. Nonempty native parameters,
+// structured output, tool search, native web search and nondefault verbosity are
+// currently native-route-only. Existing text, ordinary tools and streaming retain
+// their qualified conversion paths; no model-name heuristic establishes support.
+// Direct transport does not prove that the selected remote model accepts a native
+// parameter: the native Harness/provider remains responsible for that response.
+//
+// Input capability uses the existing MessageImages/MessageImagePlacements and
+// proto.MessageInput contracts, not another image type in model configuration.
+// Configuration preparation checks known requirements. Each Turn, steer and tool
+// result must also check newly introduced input requirements against the fixed
+// route before native submission or proxy forwarding. Unqualified image forms
+// must fail explicitly, never be dropped or reduced to text. The proxy performs
+// the final request check before forwarding; it cannot silently weaken semantics.
+
// Required execution lifecycle.
// ExecutorFactory prepares without model input. A failed factory retains any
diff --git a/apps/parsar-daemon/internal/agent/mcode/harness_config_test.go b/apps/parsar-daemon/internal/agent/mcode/harness_config_test.go
new file mode 100644
index 000000000..a8efcc9c7
--- /dev/null
+++ b/apps/parsar-daemon/internal/agent/mcode/harness_config_test.go
@@ -0,0 +1,19 @@
+package mcode
+
+import (
+ "context"
+ "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig"
+ "testing"
+)
+
+func TestNativeConfigDoesNotPretendToSupportParameters(t *testing.T) {
+ req := testRequest(t)
+ req.AgentOptions["harness_config"] = map[string]any{}
+ if _, err := prepareOptions(context.Background(), req); err != nil {
+ t.Fatal(err)
+ }
+ req.AgentOptions["harness_config"] = map[string]any{"temperature": 0.5}
+ if _, err := prepareOptions(context.Background(), req); err != harnessconfig.ErrHarnessConfig {
+ t.Fatalf("unsupported parameter accepted: %v", err)
+ }
+}
diff --git a/apps/parsar-daemon/internal/agent/mcode/options.go b/apps/parsar-daemon/internal/agent/mcode/options.go
index 507b560b6..99667df5a 100644
--- a/apps/parsar-daemon/internal/agent/mcode/options.go
+++ b/apps/parsar-daemon/internal/agent/mcode/options.go
@@ -13,6 +13,8 @@ import (
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent"
"github.com/MiniMax-AI-Dev/parsar/apps/parsar-daemon/internal/agent/claudecode"
"github.com/MiniMax-AI-Dev/parsar/internal/agentdaemon/proto"
+ harnessconfiguration "github.com/MiniMax-AI-Dev/parsar/internal/harnessconfig/mcode"
+ "github.com/MiniMax-AI-Dev/parsar/internal/modeltransport"
"github.com/MiniMax-AI-Dev/parsar/internal/obs/log"
)
@@ -28,6 +30,18 @@ func prepareOptions(ctx context.Context, req proto.PromptRequestPayload) (launch
func prepareOptionsWithSkills(ctx context.Context, req proto.PromptRequestPayload, managedSkills bool) (launchOptions, error) {
var result launchOptions
+ if _, err := harnessconfiguration.Configuration().PrepareHarnessConfig(req.AgentOptions); err != nil {
+ return result, err
+ }
+ if raw, ok := req.AgentOptions["model_provider"]; ok {
+ provider, err := modeltransport.ParseProvider(raw)
+ if err != nil {
+ return result, err
+ }
+ if err = harnessconfiguration.Configuration().ValidateRoute(string(provider.Protocol), modeltransport.RequirementsFromRequest(req)); err != nil {
+ return result, err
+ }
+ }
if req.StrictResume {
if err := validateExecutionRequest(req); err != nil {
return result, err
diff --git a/apps/web/DESIGN.md b/apps/web/DESIGN.md
index 5db5dc251..0ba727c52 100644
--- a/apps/web/DESIGN.md
+++ b/apps/web/DESIGN.md
@@ -821,13 +821,21 @@ this connection-scoped state.
### System page
Four sections, each saying where it changes. Installation: the public address, API
-base URL, installation ID and source commit as a fact card. Default model provider, the one
+base URL, installation ID and source commit as a fact card. Default model configuration, the one
section changed here: one card per harness in an auto-fill grid, its header holding
the harness name and outline actions (Set, or Replace and Clear); fact rows give the
harness's read-only startup state (a status dot and a Default pill, its source behind
-a help tip), then the provider's protocol, base URL, whether a key is configured,
+a help tip), then the default model ID, provider protocol, base URL, whether a key is configured,
token limits when set and the update time, or Not set. Set and Replace open one form
-dialog; the key field is a required password input, never prefilled or shown and
+dialog. The model ID is required; advanced settings disclose an optional JSON object
+editor with formatting and inline syntax errors, plus token limits. The existing
+harness discovery response supplies supported protocols, native protocols, JSON
+support and required limits from one adapter declaration. The form uses those
+fields without harness-specific branches. Nonempty JSON requires a native protocol;
+the form explains an incompatible selection beside the editor. Help tips explain
+the scope of native settings. Changing the model ID, provider URL or protocol
+clears the native JSON so settings cannot follow an unrelated model by accident.
+Re-entering the required write-only API key alone does not change model identity. The key field is a required password input, never prefilled or shown and
forgotten when the form closes. Core's rejection stays in red inside the form; Clear
is a ConfirmDialog. Usage details opens Core’s observations in a separate dialog.
Sandboxes: one navigation row to the Sandbox configuration secondary page; do not
diff --git a/apps/web/PRODUCT.md b/apps/web/PRODUCT.md
index d97b1ea73..fda356583 100644
--- a/apps/web/PRODUCT.md
+++ b/apps/web/PRODUCT.md
@@ -85,7 +85,7 @@ workbench.
individual node operations). Add node asks for limits before issuing its
one-time command; installers use Core's public URL and require supported node
artifacts. Removal offers the host's uninstall command. System owns installation
- facts, each harness's default model provider, startup settings, and a link to
+ facts, each harness's default model configuration, startup settings, and a link to
the Sandbox configuration secondary page. That page owns setup, resource edits,
rollout details and reset. Setup selects a backend, size and Runtime, then asks
for a deliberate save; own-machine setup continues to Add node.
diff --git a/apps/web/e2e/access.spec.ts b/apps/web/e2e/access.spec.ts
index ead3fbd2e..f22039b3c 100644
--- a/apps/web/e2e/access.spec.ts
+++ b/apps/web/e2e/access.spec.ts
@@ -53,7 +53,7 @@ test("opens a fresh install on the Overview's Getting started: a project and its
const step = (name: string) => page.getByRole("region", { name: "Getting started" }).getByRole("listitem").filter({ hasText: name });
// The fixture deployment already has a ready node.
await expect(step("Get sandboxes ready")).toContainText("Done");
- await expect(step("Set a default model provider")).toContainText("To do");
+ await expect(step("Set a default model configuration")).toContainText("To do");
await expect(step("Create a project and issue a key")).toContainText("To do");
await expect(step("Run the first Session")).toContainText("To do");
@@ -103,21 +103,22 @@ test("opens a fresh install on the Overview's Getting started: a project and its
expect(stored).not.toContain(FIXTURE_CORE_KEY);
});
-test("leads from Getting started to the default model provider, and counts it done once the default harness has one", async ({ page, request }) => {
+test("leads from Getting started to the default model configuration, and counts it done once the default harness has one", async ({ page, request }) => {
await openConsole(page, request, "overview", { fresh: true });
- const step = page.getByRole("region", { name: "Getting started" }).getByRole("listitem").filter({ hasText: "Set a default model provider" });
+ const step = page.getByRole("region", { name: "Getting started" }).getByRole("listitem").filter({ hasText: "Set a default model configuration" });
await expect(step).toContainText("To do");
await step.getByRole("button", { name: "Open System" }).click();
await expect(page.getByRole("heading", { name: "System", level: 1 })).toBeVisible();
// It arrives on the default harness's action.
- const set = page.getByRole("button", { name: "Set the default model provider for Codex" });
+ const set = page.getByRole("button", { name: "Set the default model configuration for Codex" });
await expect(set).toBeFocused();
// Only the page body scrolls to it: the page header stays in view.
await expect(page.getByRole("heading", { name: "System", level: 1 })).toBeInViewport();
await set.click();
- const form = page.getByRole("dialog", { name: "Set default model provider for Codex" });
+ const form = page.getByRole("dialog", { name: "Set default model configuration for Codex" });
await form.getByLabel("Base URL").fill("https://model.example/v1");
await form.getByLabel("API key").fill("sk-fixture-getting-started");
+ await form.getByLabel("Default model ID").fill("fixture-model");
await form.getByRole("button", { name: "Save" }).click();
await expect(form).toBeHidden();
await page.getByRole("button", { name: "Overview", exact: true }).click();
diff --git a/apps/web/e2e/fixture-console.mjs b/apps/web/e2e/fixture-console.mjs
index 07f4e49ab..074d214b0 100644
--- a/apps/web/e2e/fixture-console.mjs
+++ b/apps/web/e2e/fixture-console.mjs
@@ -117,7 +117,7 @@ function reset(mode = "login", fresh = false, sandbox = "configured", nodes = "d
// The demo deployment's default harness has a default model; a fresh install has none.
harnesses: {
claude_sdk: { enabled: true, default: false, provider: null },
- codex: { enabled: true, default: true, provider: fresh ? null : { object: "core.model_provider", harness: "codex", protocol: "responses", base_url: "https://model.example/v1", api_key_configured: true, last_used_at: null, last_error_code: null, last_error_at: null, updated_at: new Date((now - 86400) * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") } },
+ codex: { enabled: true, default: true, provider: fresh ? null : { object: "core.model_configuration", harness: "codex", model: "fixture-model", harness_config: {}, model_provider: { protocol: "responses", base_url: "https://model.example/v1", api_key_configured: true }, last_used_at: null, last_error_code: null, last_error_at: null, updated_at: new Date((now - 86400) * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") } },
mcode: { enabled: false, default: false, provider: null },
},
// "none": the deployment is not configured yet, so the Nodes page offers setup.
@@ -496,7 +496,7 @@ function registeredNode(nodeId) {
return { rollout: { state: "unknown", ready_generation: null }, id: nodeId, name: nodeId, provider: state.deployment?.provider ?? "docker", core_url: publicUrl(), enrollment_id, online: false, provider_ready: false, cpu_count: null, available_memory_bytes: null, available_disk_bytes: null, running: 0, snapshots: 0, last_seen_at: null, ...limits, active: 0, reserved: 0, retained: 0, cleanup_pending: 0, created_at: new Date().toISOString() };
}
-const HARNESS_PROVIDER = /^\/harnesses\/([^/]+)\/model-provider$/;
+const HARNESS_PROVIDER = /^\/harnesses\/([^/]+)\/model-configuration$/;
const PROVIDER_FIELDS = new Set(["protocol", "base_url", "api_key", "context_window", "max_output_tokens"]);
/** Core's one message for a body that is not a complete provider; it never echoes a value. */
const PROVIDER_SHAPE = "The body must be a complete model provider: protocol, base_url, api_key and optional nonnegative context_window and max_output_tokens.";
@@ -526,7 +526,8 @@ function providerProblem(harness, input) {
* DELETE is 204 and safe to repeat. A disabled harness may still be configured.
*/
async function harnessRoute(request, response, path) {
- const view = (id) => ({ object: "core.harness", id, enabled: state.harnesses[id].enabled, default: state.harnesses[id].default, model_provider: state.harnesses[id].provider });
+ const support = (id) => ({ protocols: ["anthropic", "responses", "chat_completions"], native_protocols: id === "codex" ? ["responses"] : id === "claude_sdk" ? ["anthropic"] : ["anthropic", "responses", "chat_completions"], accepts_harness_config: id !== "mcode", token_limits_required: id === "mcode" });
+ const view = (id) => ({ model_configuration_support: support(id), object: "core.harness", id, enabled: state.harnesses[id].enabled, default: state.harnesses[id].default, model_configuration: state.harnesses[id].provider });
if (path === "/harnesses" && request.method === "GET") return send(response, 200, { object: "list", data: Object.keys(state.harnesses).map(view) });
const match = path.match(HARNESS_PROVIDER);
const harness = match && Object.hasOwn(state.harnesses, match[1]) ? match[1] : null;
@@ -551,14 +552,19 @@ async function harnessRoute(request, response, path) {
}
input ??= {};
if (typeof input !== "object" || Array.isArray(input)) return error(response, 400, `Invalid type: expected an object, but got ${jsonKind(input)} instead.`, "invalid_request_error");
- const problem = providerProblem(harness, input);
+ if (typeof input.model !== "string" || !input.model.trim()) return error(response, 400, "A model ID is required.", "model_configuration_model_invalid");
+ if (input.harness_config !== undefined && (!input.harness_config || typeof input.harness_config !== "object" || Array.isArray(input.harness_config))) return error(response, 400, "Harness configuration must be an object.", "harness_config_invalid");
+ if (Object.keys(input.harness_config ?? {}).length && !support(harness).native_protocols.includes(input.model_provider?.protocol)) return error(response, 400, "The selected route cannot preserve native model settings.", "model_configuration_route_unsupported");
+ const problem = providerProblem(harness, input.model_provider ?? {});
if (problem) return error(response, 400, problem, "invalid_request_error");
// As Core's error mapping: sealing the key needs the credential encryption key.
if (!state.credentialKey) return error(response, 503, "Credential encryption is not configured on this service.", "credential_storage_unavailable");
entry.provider = {
- object: "core.model_provider", harness, protocol: input.protocol, base_url: input.base_url, api_key_configured: true,
- ...(input.context_window ? { context_window: input.context_window } : {}),
- ...(input.max_output_tokens ? { max_output_tokens: input.max_output_tokens } : {}),
+ object: "core.model_configuration", harness, model: input.model, harness_config: input.harness_config ?? {},
+ model_provider: { protocol: input.model_provider.protocol, base_url: input.model_provider.base_url, api_key_configured: true,
+ ...(input.model_provider.context_window ? { context_window: input.model_provider.context_window } : {}),
+ ...(input.model_provider.max_output_tokens ? { max_output_tokens: input.model_provider.max_output_tokens } : {}),
+ },
last_used_at: null, last_error_code: null, last_error_at: null,
updated_at: new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
};
diff --git a/apps/web/e2e/provider-observations.spec.ts b/apps/web/e2e/provider-observations.spec.ts
index b3fd750d3..c45ab1aca 100644
--- a/apps/web/e2e/provider-observations.spec.ts
+++ b/apps/web/e2e/provider-observations.spec.ts
@@ -10,7 +10,7 @@ test("default provider observations are optional details and recover only on Cor
if (fail) return route.fulfill({ status: 503, json: { error: { code: "internal_error", message: "Read unavailable", type: "server_error", param: null } } });
const response = await route.fetch();
const data = await response.json();
- for (const harness of data.data) if (harness.model_provider) Object.assign(harness.model_provider, observation);
+ for (const harness of data.data) if (harness.model_configuration) Object.assign(harness.model_configuration, observation);
await route.fulfill({ response, json: data });
});
await openConsole(page, request, "system");
diff --git a/apps/web/e2e/system.spec.ts b/apps/web/e2e/system.spec.ts
index 52e485da6..87d952874 100644
--- a/apps/web/e2e/system.spec.ts
+++ b/apps/web/e2e/system.spec.ts
@@ -6,10 +6,10 @@ test.afterEach(async ({ request }) => expectManagementBoundary(request));
const KEY = "sk-fixture-default-model-canary";
-test("sets, replaces and clears a harness's default model provider, and keeps its key out of the browser", async ({ page, request }) => {
- // A fresh install: no harness has a default model provider yet.
+test("sets, replaces and clears a harness's default model configuration, and keeps its key out of the browser", async ({ page, request }) => {
+ // A fresh install: no harness has a default model configuration yet.
await openConsole(page, request, "system", { fresh: true });
- const section = page.getByRole("region", { name: "Default model provider" });
+ const section = page.getByRole("region", { name: "Default model configuration" });
const codex = section.getByRole("article", { name: "Codex" });
const mcode = section.getByRole("article", { name: "MiniMax Code" });
await expect(codex).toContainText("Enabled");
@@ -18,8 +18,8 @@ test("sets, replaces and clears a harness's default model provider, and keeps it
await expect(section.getByRole("article", { name: "Claude Code" })).toContainText("Not set");
await expect(mcode).toContainText("Disabled");
- await codex.getByRole("button", { name: "Set the default model provider for Codex" }).click();
- const set = page.getByRole("dialog", { name: "Set default model provider for Codex" });
+ await codex.getByRole("button", { name: "Set the default model configuration for Codex" }).click();
+ const set = page.getByRole("dialog", { name: "Set default model configuration for Codex" });
await expect(set.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("OpenAI Responses");
await set.getByRole("combobox", { name: "Protocol", exact: true }).click();
await expect(page.getByRole("option")).toHaveText(["Anthropic Messages", "OpenAI Responses", "OpenAI Chat Completions"]);
@@ -27,7 +27,8 @@ test("sets, replaces and clears a harness's default model provider, and keeps it
await page.getByRole("option", { name: "OpenAI Chat Completions", exact: true }).click();
await set.getByLabel("Base URL").fill("https://model.example/v1");
await set.getByLabel("API key").fill(KEY);
- await expect(set).toContainText("Your application specifies the model in the Agent’s model field.");
+ await set.getByLabel("Default model ID").fill("fixture-model");
+ await expect(set).toContainText("Used for new Sessions when the application does not specify a model.");
// Every rejected URL stays local; Enter cannot bypass validation or write a secret.
for (const url of ["http://model.example/v1", "ftp://model.example", "https://user:password@model.example/v1", "https://@model.example/v1", "https:model.example/v1", "https://model.example/v1?token=x", "https://model.example/v1#fragment", "https://model.example/v1?", "https://model.example/v1#", "not a URL"]) {
await set.getByLabel("Base URL").fill(url);
@@ -37,6 +38,22 @@ test("sets, replaces and clears a harness's default model provider, and keeps it
}
expect(await writes(request)).toEqual([]);
await set.getByLabel("Base URL").fill("https://model.example/v1");
+ await expect(set.getByLabel("Harness configuration (JSON)")).toBeHidden();
+ await set.getByText("Advanced settings", { exact: true }).click();
+ const config = set.getByLabel("Harness configuration (JSON)");
+ await config.fill("[]");
+ await config.blur();
+ await expect(set.getByText("Enter a valid JSON object, such as {}.")).toBeVisible();
+ await expect(set.getByRole("button", { name: "Save", exact: true })).toBeDisabled();
+ await config.fill('{"model_reasoning_effort":"high"}');
+ await set.getByRole("button", { name: "Format JSON" }).click();
+ await expect(config).toHaveValue('{\n "model_reasoning_effort": "high"\n}');
+ await expect(set.getByText("Advanced model settings require a native protocol for this harness. Change the protocol or clear the JSON object.")).toBeVisible();
+ await expect(set.getByRole("button", { name: "Save", exact: true })).toBeDisabled();
+ await set.getByRole("combobox", { name: "Protocol", exact: true }).click();
+ await page.getByRole("option", { name: "OpenAI Responses", exact: true }).click();
+ await expect(config).toHaveValue("{}");
+ await config.fill('{"model_reasoning_effort":"high"}');
// Limits are Core's 32-bit whole numbers, and max output needs a context window at least as large.
await set.getByLabel("Max output tokens").fill("32000");
await expect(set.getByText("Set a context window at least this large.")).toBeVisible();
@@ -51,59 +68,72 @@ test("sets, replaces and clears a harness's default model provider, and keeps it
await set.getByLabel("Context window").fill("200000");
await set.getByRole("button", { name: "Save" }).click();
await expect(set).toBeHidden();
- for (const text of ["OpenAI Chat Completions", "https://model.example/v1", "Configured", "200,000", "32,000"]) await expect(codex).toContainText(text);
+ for (const text of ["OpenAI Responses", "https://model.example/v1", "Configured", "200,000", "32,000"]) await expect(codex).toContainText(text);
expect(await page.content()).not.toContain(KEY);
// Replacing starts from the saved fields but never from the key; closing the form forgets a typed key.
- await codex.getByRole("button", { name: "Replace the default model provider for Codex" }).click();
- let replace = page.getByRole("dialog", { name: "Replace default model provider for Codex" });
- await expect(replace.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("OpenAI Chat Completions");
+ await codex.getByRole("button", { name: "Replace the default model configuration for Codex" }).click();
+ let replace = page.getByRole("dialog", { name: "Replace default model configuration for Codex" });
+ await expect(replace.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("OpenAI Responses");
+ await expect(replace.getByLabel("Default model ID")).toHaveValue("fixture-model");
+ await expect(replace.getByLabel("Harness configuration (JSON)")).toHaveValue(/model_reasoning_effort/);
await expect(replace.getByLabel("Base URL")).toHaveValue("https://model.example/v1");
await expect(replace.getByLabel("API key")).toHaveValue("");
await expect(replace.getByRole("button", { name: "Save" })).toBeDisabled();
await replace.getByLabel("API key").fill(KEY);
+ const nativeSettings = replace.getByLabel("Harness configuration (JSON)");
+ await expect(nativeSettings).toHaveValue(/model_reasoning_effort/);
+ await replace.getByLabel("Default model ID").fill("different-model");
+ await expect(nativeSettings).toHaveValue("{}");
+ await nativeSettings.fill('{"model_reasoning_effort":"low"}');
+ await replace.getByLabel("Base URL").fill("https://another-model.example/v1");
+ await expect(nativeSettings).toHaveValue("{}");
+ await nativeSettings.fill('{"model_reasoning_effort":"high"}');
await replace.getByRole("combobox", { name: "Protocol", exact: true }).click();
await page.getByRole("option", { name: "Anthropic Messages", exact: true }).click();
+ await expect(nativeSettings).toHaveValue("{}");
await replace.getByRole("button", { name: "Cancel" }).click();
expect(await page.content()).not.toContain(KEY);
- await codex.getByRole("button", { name: "Replace the default model provider for Codex" }).click();
- replace = page.getByRole("dialog", { name: "Replace default model provider for Codex" });
- await expect(replace.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("OpenAI Chat Completions");
+ await codex.getByRole("button", { name: "Replace the default model configuration for Codex" }).click();
+ replace = page.getByRole("dialog", { name: "Replace default model configuration for Codex" });
+ await expect(replace.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("OpenAI Responses");
+ await expect(replace.getByLabel("Default model ID")).toHaveValue("fixture-model");
+ await expect(replace.getByLabel("Harness configuration (JSON)")).toHaveValue(/model_reasoning_effort/);
await replace.getByRole("combobox", { name: "Protocol", exact: true }).click();
await page.getByRole("option", { name: "Anthropic Messages", exact: true }).click();
await expect(replace.getByLabel("API key")).toHaveValue("");
await replace.getByLabel("Base URL").fill("https://model.example/v2");
await replace.getByLabel("API key").fill(KEY);
+ await expect(replace.getByLabel("Harness configuration (JSON)")).toHaveValue("{}");
// Enter saves.
await replace.getByLabel("API key").press("Enter");
await expect(replace).toBeHidden();
await expect(codex).toContainText("https://model.example/v2");
await expect(codex).toContainText("Anthropic Messages");
- await codex.getByRole("button", { name: "Clear the default model provider for Codex" }).click();
- const confirm = page.getByRole("dialog", { name: "Clear default model provider" });
- await confirm.getByRole("button", { name: "Clear default model provider" }).click();
+ await codex.getByRole("button", { name: "Clear the default model configuration for Codex" }).click();
+ const confirm = page.getByRole("dialog", { name: "Clear default model configuration" });
+ await confirm.getByRole("button", { name: "Clear default model configuration" }).click();
await expect(confirm).toBeHidden();
await expect(codex).toContainText("Not set");
// MiniMax Code needs both limits; the form shows Core's reason. A disabled harness may still be configured.
- await mcode.getByRole("button", { name: "Set the default model provider for MiniMax Code" }).click();
- const limits = page.getByRole("dialog", { name: "Set default model provider for MiniMax Code" });
+ await mcode.getByRole("button", { name: "Set the default model configuration for MiniMax Code" }).click();
+ const limits = page.getByRole("dialog", { name: "Set default model configuration for MiniMax Code" });
await expect(limits.getByRole("combobox", { name: "Protocol", exact: true })).toHaveText("Anthropic Messages");
await limits.getByRole("combobox", { name: "Protocol", exact: true }).click();
await page.getByRole("option", { name: "OpenAI Responses", exact: true }).click();
await limits.getByLabel("Base URL").fill("https://model.example/anthropic");
await limits.getByLabel("API key").fill(KEY);
- await limits.getByRole("button", { name: "Save" }).click();
- await expect(limits.getByRole("alert")).toHaveText("selected harness requires positive model context_window and max_output_tokens");
+ await limits.getByLabel("Default model ID").fill("fixture-model");
+ await expect(limits.getByRole("button", { name: "Save" })).toBeDisabled();
await limits.getByRole("button", { name: "Cancel" }).click();
await expect(mcode).toContainText("Not set");
expect(await writes(request)).toEqual([
- "PUT /core/v1/harnesses/codex/model-provider",
- "PUT /core/v1/harnesses/codex/model-provider",
- "DELETE /core/v1/harnesses/codex/model-provider",
- "PUT /core/v1/harnesses/mcode/model-provider",
+ "PUT /core/v1/harnesses/codex/model-configuration",
+ "PUT /core/v1/harnesses/codex/model-configuration",
+ "DELETE /core/v1/harnesses/codex/model-configuration",
]);
const browserState = await page.evaluate(() => JSON.stringify({ local: { ...localStorage }, session: { ...sessionStorage }, url: location.href, cookie: document.cookie }));
expect(browserState).not.toContain(KEY);
@@ -111,36 +141,38 @@ test("sets, replaces and clears a harness's default model provider, and keeps it
test("reports a Core without a credential key as a configuration error, without rereading", async ({ page, request }) => {
await openConsole(page, request, "system", { fresh: true, credentials: "none" });
- const codex = page.getByRole("region", { name: "Default model provider" }).getByRole("article", { name: "Codex" });
- await codex.getByRole("button", { name: "Set the default model provider for Codex" }).click();
- const set = page.getByRole("dialog", { name: "Set default model provider for Codex" });
+ const codex = page.getByRole("region", { name: "Default model configuration" }).getByRole("article", { name: "Codex" });
+ await codex.getByRole("button", { name: "Set the default model configuration for Codex" }).click();
+ const set = page.getByRole("dialog", { name: "Set default model configuration for Codex" });
await set.getByLabel("Base URL").fill("https://model.example/v1");
await set.getByLabel("API key").fill(KEY);
+ await set.getByLabel("Default model ID").fill("fixture-model");
const reads: string[] = [];
page.on("request", (sent) => { if (sent.method() === "GET" && new URL(sent.url()).pathname === "/core/v1/harnesses") reads.push(sent.url()); });
await set.getByRole("button", { name: "Save" }).click();
await expect(set.getByRole("alert")).toHaveText("Core has no credential encryption key configured, so it can't store keys. Installer-based installs configure this automatically; for manual deployments, set OAC_CREDENTIAL_KEY_FILE for Core.");
await expect(set.getByRole("button", { name: "Save" })).toBeEnabled();
expect(reads).toEqual([]);
- expect(await writes(request)).toEqual(["PUT /core/v1/harnesses/codex/model-provider"]);
+ expect(await writes(request)).toEqual(["PUT /core/v1/harnesses/codex/model-configuration"]);
await set.getByRole("button", { name: "Cancel" }).click();
await expect(codex).toContainText("Not set");
});
-test("reports an unconfirmed save, reads the default model providers again once and never repeats the write", async ({ page, request }) => {
+test("reports an unconfirmed save, reads the default model configurations again once and never repeats the write", async ({ page, request }) => {
await openConsole(page, request, "system", { fresh: true });
- const codex = page.getByRole("region", { name: "Default model provider" }).getByRole("article", { name: "Codex" });
- await codex.getByRole("button", { name: "Set the default model provider for Codex" }).click();
- const set = page.getByRole("dialog", { name: "Set default model provider for Codex" });
+ const codex = page.getByRole("region", { name: "Default model configuration" }).getByRole("article", { name: "Codex" });
+ await codex.getByRole("button", { name: "Set the default model configuration for Codex" }).click();
+ const set = page.getByRole("dialog", { name: "Set default model configuration for Codex" });
await set.getByLabel("Base URL").fill("https://model.example/v1");
await set.getByLabel("API key").fill(KEY);
- await failNext(request, { method: "PUT", path: "/harnesses/codex/model-provider", status: 500 });
+ await set.getByLabel("Default model ID").fill("fixture-model");
+ await failNext(request, { method: "PUT", path: "/harnesses/codex/model-configuration", status: 500 });
const reads: string[] = [];
page.on("request", (sent) => { if (sent.method() === "GET" && new URL(sent.url()).pathname === "/core/v1/harnesses") reads.push(sent.url()); });
await set.getByRole("button", { name: "Save" }).click();
- await expect(set.getByRole("alert")).toHaveText("Core did not confirm the change. The default model providers were read again; check them before trying again.");
+ await expect(set.getByRole("alert")).toHaveText("Core did not confirm the change. The default model configurations were read again; check them before trying again.");
await expect.poll(() => reads.length).toBe(1);
await page.waitForTimeout(500);
expect(reads).toHaveLength(1);
- expect(await writes(request)).toEqual(["PUT /core/v1/harnesses/codex/model-provider"]);
+ expect(await writes(request)).toEqual(["PUT /core/v1/harnesses/codex/model-configuration"]);
});
diff --git a/apps/web/src/features/overview/getting-started.test.ts b/apps/web/src/features/overview/getting-started.test.ts
index 84e2ed166..ba292316b 100644
--- a/apps/web/src/features/overview/getting-started.test.ts
+++ b/apps/web/src/features/overview/getting-started.test.ts
@@ -11,8 +11,8 @@ const deployment = (overrides: Partial = {}): SandboxDeployme
});
const fleet = (value: SandboxDeployment, nodes = [node("n1")]): FleetState => ({ status: "ready", snapshot: { deployment: value, nodes, allocations: [], loadedAt: 0 }, targetGeneration: value.generation, refreshing: false, error: null });
const sandboxes = (state: FleetState) => gettingStartedSteps({ sandboxReset: false, fleet: state, localOnly: false, projects: [], sessions: 0, harnesses: [] }).sandboxes;
-const provider = { object: "core.model_provider", protocol: "responses", base_url: "https://model.example/v1", api_key_configured: true, last_used_at: null, last_error_code: null, last_error_at: null, updated_at: "2026-09-25T00:00:00Z" } as const;
-const harness = (id: CoreHarness["id"], fields: Partial = {}): CoreHarness => ({ object: "core.harness", id, enabled: true, default: false, model_provider: null, ...fields });
+const provider = { object: "core.model_configuration", model: "fixture-model", harness_config: {}, model_provider: { protocol: "responses", base_url: "https://model.example/v1", api_key_configured: true }, last_used_at: null, last_error_code: null, last_error_at: null, updated_at: "2026-09-25T00:00:00Z" } as const;
+const harness = (id: CoreHarness["id"], fields: Partial = {}): CoreHarness => ({ object: "core.harness", model_configuration_support: { protocols: ["responses"], native_protocols: ["responses"], accepts_harness_config: true, token_limits_required: false }, id, enabled: true, default: false, model_configuration: null, ...fields });
describe("Getting started steps", () => {
it("uses live provider readiness independently of target state or a durable pin", () => {
@@ -29,7 +29,7 @@ describe("Getting started steps", () => {
it("does not report ready during reset or an unreadable deployment, even with ready nodes", () => {
for (const backend of ["docker", "e2b"] as const) {
const input = { fleet: fleet(deployment({ provider: backend })), localOnly: false, projects: [project("p")], sessions: 1,
- harnesses: [harness("codex", { default: true, model_provider: { ...provider, harness: "codex" } })] };
+ harnesses: [harness("codex", { default: true, model_configuration: { ...provider, harness: "codex" } })] };
for (const sandboxReset of [true, "failed", undefined] as const) {
const steps = gettingStartedSteps({ ...input, sandboxReset });
expect(steps.sandboxes).toMatchObject({ state: sandboxReset === true ? "todo" : sandboxReset === "failed" ? "unknown" : null, action: "nodes" });
@@ -47,7 +47,7 @@ describe("Getting started steps", () => {
it("cannot complete onboarding while the installation read is pending or failed", () => {
for (const localOnly of [undefined, "failed"] as const) {
const steps = gettingStartedSteps({ sandboxReset: false, localOnly, fleet: fleet(deployment()), projects: [project("p")], sessions: 1,
- harnesses: [harness("codex", { default: true, model_provider: { ...provider, harness: "codex" } })] });
+ harnesses: [harness("codex", { default: true, model_configuration: { ...provider, harness: "codex" } })] });
expect(steps.sandboxes.state).toBe(localOnly === "failed" ? "unknown" : null);
expect(checklistView([steps.sandboxes.state, steps.model, steps.key.state, steps.session.state], "open")).toBe("full");
}
@@ -97,10 +97,10 @@ describe("Getting started steps", () => {
it("needs a default model on the default harness, or on any enabled harness when none is default", () => {
const model = (harnesses: Parameters[0]["harnesses"]) => gettingStartedSteps({ sandboxReset: false, fleet: { status: "loading" }, projects: undefined, sessions: null, harnesses }).model;
const on = (id: CoreHarness["id"]) => ({ ...provider, harness: id });
- expect(model([harness("codex", { default: true }), harness("claude_sdk", { model_provider: on("claude_sdk") })])).toBe("todo");
- expect(model([harness("codex", { default: true, model_provider: on("codex") })])).toBe("done");
- expect(model([harness("codex"), harness("mcode", { enabled: false, model_provider: on("mcode") })])).toBe("todo");
- expect(model([harness("codex"), harness("claude_sdk", { model_provider: on("claude_sdk") })])).toBe("done");
+ expect(model([harness("codex", { default: true }), harness("claude_sdk", { model_configuration: on("claude_sdk") })])).toBe("todo");
+ expect(model([harness("codex", { default: true, model_configuration: on("codex") })])).toBe("done");
+ expect(model([harness("codex"), harness("mcode", { enabled: false, model_configuration: on("mcode") })])).toBe("todo");
+ expect(model([harness("codex"), harness("claude_sdk", { model_configuration: on("claude_sdk") })])).toBe("done");
expect(model(undefined)).toBeNull();
expect(model("failed")).toBe("unknown");
});
diff --git a/apps/web/src/features/overview/getting-started.ts b/apps/web/src/features/overview/getting-started.ts
index 1d1758964..0fa930fb5 100644
--- a/apps/web/src/features/overview/getting-started.ts
+++ b/apps/web/src/features/overview/getting-started.ts
@@ -82,7 +82,7 @@ function sandboxStep(fleet: FleetState): GettingStartedSteps["sandboxes"] {
export function modelStep(harnesses: readonly CoreHarness[] | "failed" | undefined): StepState {
if (!harnesses || harnesses === "failed") return harnesses ? "unknown" : null;
const target = harnesses.find((harness) => harness.default);
- const set = target ? target.model_provider !== null : harnesses.some((harness) => harness.enabled && harness.model_provider !== null);
+ const set = target ? target.model_configuration !== null : harnesses.some((harness) => harness.enabled && harness.model_configuration !== null);
return set ? "done" : "todo";
}
diff --git a/apps/web/src/features/system/DefaultModelsSection.tsx b/apps/web/src/features/system/DefaultModelsSection.tsx
index 0238010d8..31cb3a130 100644
--- a/apps/web/src/features/system/DefaultModelsSection.tsx
+++ b/apps/web/src/features/system/DefaultModelsSection.tsx
@@ -1,65 +1,32 @@
-import { AgentCoreError, type CoreHarness, type CoreHarnessKind, type ModelProviderInput } from "@agents-core-web/agents-client";
+import { type CoreHarnessKind } from "@agents-core-web/agents-client";
import { useQuery, useQueryClient } from "@tanstack/react-query";
-import { useCallback, useId, useRef, useState, type ReactNode } from "react";
+import { useCallback, useState, type ReactNode } from "react";
import { useTranslation } from "react-i18next";
-import { ConsoleSelect } from "../../components/console-select";
import { ConfirmDialog } from "../../components/ConfirmDialog";
-import { EmptyState, HelpTip, revealInPageBody, Section } from "../../components/console-ui";
+import { EmptyState, revealInPageBody, Section } from "../../components/console-ui";
import { ErrorState } from "../../components/ErrorState";
-import { Modal } from "../../components/Modal";
import { TableSkeleton } from "../../components/Skeleton";
import { failedLast, useFailureToast, useToast } from "../../components/Toast";
-import { coreError, coreFieldError } from "../../lib/core-error";
import { useDeleteFlow } from "../../lib/delete-flow";
-import { formatInteger } from "../../lib/format";
import { useConsoleIntent } from "../../lib/console-navigation";
-import { harnessNames, protocolNames } from "../../lib/harness-labels";
+import { harnessNames } from "../../lib/harness-labels";
import { admin } from "../../lib/projects";
+import { ModelProviderDialog } from "./ModelProviderDialog";
import { HarnessCard } from "./HarnessCard";
import { harnessesQuery } from "./harness-queries";
-/** A write that gets no answer in this time has an unknown outcome. */
-const WRITE_TIMEOUT_MS = 30_000;
-
-type Protocol = ModelProviderInput["protocol"];
-/** New providers start with the harness native protocol; saved providers keep their upstream protocol. */
-const defaultHarnessProtocol: Record = { codex: "responses", claude_sdk: "anthropic", mcode: "anthropic" };
-const protocolOptions = (["anthropic", "responses", "chat_completions"] as const).map((value) => ({ value, label: protocolNames[value] }));
-/** Core stores both token limits as 32-bit integers. */
-const INT32_MAX = 2_147_483_647;
-
function message(error: unknown): string {
return error instanceof Error ? error.message : String(error ?? "");
}
-/** A token limit: empty is omitted; anything but a whole number within Core's range is a problem. */
-function tokenLimit(text: string): { value: number | undefined; problem: "whole" | "large" | null } {
- const value = text.trim();
- if (!value) return { value: undefined, problem: null };
- if (!/^\d+$/u.test(value)) return { value: undefined, problem: "whole" };
- const number = Number(value);
- return number > INT32_MAX ? { value: undefined, problem: "large" } : { value: number, problem: null };
-}
-
-function isProviderUrl(value: string): boolean {
- try {
- const url = new URL(value);
- const authority = /^https:\/\/([^/]+)/iu.exec(value)?.[1];
- return authority !== undefined && url.protocol === "https:" && url.hostname !== "" && !authority.includes("@")
- && !/[\\\s?#]/u.test(value);
- } catch {
- return false;
- }
-}
-
/**
- * System › Default model provider: each harness's deployment default model provider.
- * It applies to Core-hosted Sessions, after a provider in the request or on
- * the Agent, and is the only source for Sessions without an environment;
- * self-hosted Sessions bring their own. Whether a harness is enabled, and
+ * System owns each harness's deployment default model configuration.
+ * New Core-hosted Sessions and Sessions without an environment inherit it
+ * when no explicit Session or Agent model configuration takes precedence.
+ * Self-hosted Sessions bring their own configuration. Whether a harness is enabled, and
* which is the default, is Core's startup configuration and only shown here.
- * A write replaces the whole provider and needs the API key every time; the
+ * A write replaces the whole model configuration and needs the API key every time; the
* key lives only in the open form's state, never in the query cache, storage
* or the URL. Writes are never retried automatically; after each one the
* harnesses are read again.
@@ -86,7 +53,7 @@ export function DefaultModelsSection() {
const editingHarness = (editing && harnesses?.find((harness) => harness.id === editing)) || null;
const clear = useDeleteFlow(
async (harness) => {
- await admin.deleteHarnessModelProvider(harness, { signal: AbortSignal.timeout(WRITE_TIMEOUT_MS) });
+ await admin.deleteHarnessModelConfiguration(harness, { signal: AbortSignal.timeout(30_000) });
toast.show(t("models.cleared", { harness: harnessNames[harness] }), { tone: "success" });
},
reread,
@@ -145,159 +112,3 @@ export function DefaultModelsSection() {
);
}
-
-
-
-/**
- * Sets or replaces one harness's provider. Non-secret fields start from the
- * current provider; the API key never does. The protocol describes the upstream
- * model provider. The form checks the HTTPS provider URL and whole-number
- * limits within Core's range, with max output no larger than the context window.
- * Core's typed rejection is shown beside its field, or beside the form
- * when no editable field applies. Enter saves; a save in flight blocks another.
- */
-function ModelProviderDialog({ harness, onClose, onSaved, onReread }: {
- harness: CoreHarness | null;
- onClose: () => void;
- onSaved: (harness: CoreHarnessKind) => void;
- onReread: () => void;
-}) {
- const { t } = useTranslation("system");
- const { t: tCommon } = useTranslation();
- const id = useId();
- const formId = `${id}-form`;
- const current = harness?.model_provider ?? null;
- const [protocol, setProtocol] = useState(current?.protocol ?? (harness ? defaultHarnessProtocol[harness.id] : "responses"));
- const [baseUrl, setBaseUrl] = useState(current?.base_url ?? "");
- const [apiKey, setApiKey] = useState("");
- const [contextWindow, setContextWindow] = useState(current?.context_window === undefined ? "" : String(current.context_window));
- const [maxOutputTokens, setMaxOutputTokens] = useState(current?.max_output_tokens === undefined ? "" : String(current.max_output_tokens));
- const [busy, setBusy] = useState(false);
- const saving = useRef(false);
- const [error, setError] = useState(null);
- const [rejection, setRejection] = useState(null);
- const fieldError = (param: string) => coreFieldError(rejection, param, tCommon);
-
- const name = harness ? harnessNames[harness.id] : "";
- const limitsRequired = harness?.id === "mcode";
- const url = baseUrl.trim();
- const urlProblem = url && !isProviderUrl(url) ? t("models.form.baseUrlInvalid") : null;
- const context = tokenLimit(contextWindow);
- const output = tokenLimit(maxOutputTokens);
- const limitProblem = (limit: ReturnType) => (limit.problem === "whole" ? t("models.form.wholeNumber") : limit.problem === "large" ? t("models.form.tooLarge") : null);
- const outputProblem = limitProblem(output);
- // The missing or undersized window is the field the administrator must fix.
- const contextProblem = limitProblem(context) ?? (!outputProblem && output.value !== undefined && output.value > (context.value ?? 0) ? t("models.form.needsContext") : null);
- const ready = harness !== null && !busy && url !== "" && !urlProblem && apiKey.trim() !== "" && !contextProblem && !outputProblem;
-
- async function save() {
- if (!ready || !harness || saving.current) return;
- saving.current = true;
- setBusy(true);
- setError(null); setRejection(null);
- try {
- await admin.setHarnessModelProvider(harness.id, {
- protocol, base_url: url, api_key: apiKey.trim(),
- ...(context.value === undefined ? {} : { context_window: context.value }),
- ...(output.value === undefined ? {} : { max_output_tokens: output.value }),
- }, { signal: AbortSignal.timeout(WRITE_TIMEOUT_MS) });
- onSaved(harness.id);
- } catch (caught) {
- // Never retried: a rejection shows Core's reason; an unknown outcome is read again first.
- if (caught instanceof AgentCoreError && caught.status >= 400 && caught.status < 500 && caught.status !== 408) {
- setRejection(caught);
- setError(coreError(caught, tCommon));
- } else if (caught instanceof AgentCoreError && caught.code === "credential_storage_unavailable") {
- // A deployment without a credential key stores nothing: a configuration error, not an unknown outcome.
- setError(t("models.form.noCredentialKey"));
- } else {
- setError(t("models.form.uncertain"));
- onReread();
- }
- } finally {
- saving.current = false;
- setBusy(false);
- }
- }
-
- const limitField = (field: "context" | "output", value: string, setValue: (value: string) => void, problem: string | null) => {
- const inputId = `${id}-${field}`;
- problem = problem ?? fieldError(field === "context" ? "context_window" : "max_output_tokens");
- return (
-