From 7c733e6131d67404c6e74f8fbdb6f9982f3afce7 Mon Sep 17 00:00:00 2001 From: saladday <1203511142@qq.com> Date: Tue, 29 Sep 2026 18:35:30 +0800 Subject: [PATCH 1/2] docs: simplify the new-user path and give each topic one owner - README: what the project is, a four-step install, the two APIs and a documentation table by goal (English and Chinese). - Installation: the default path first (prerequisites, install, reachability, sign-in, next steps); version, sandbox backend, modes, split deployment and directory layout move to "Advanced installation". - Quickstart: three steps from a Project API key to a finished Session. - User guide: task-oriented, and now the single owner of Environment kinds, harness and model choice, and model provider precedence. - Remove repeated explanations and link to one owner instead: namespaces and credentials (API index), Projects and keys and administrator authority and isolation (design principles), key rotation steps (operations), backend and size changes (configuration), executor credential rotation (self-hosted). --- README.md | 85 ++-- README.zh-CN.md | 69 ++-- docs/architecture.md | 29 +- docs/configuration.md | 26 +- docs/design-principles.md | 166 ++++---- docs/getting-started/README.md | 63 ++- docs/getting-started/install.md | 611 +++++++++++++--------------- docs/getting-started/nodes.md | 12 +- docs/getting-started/operations.md | 20 +- docs/getting-started/quickstart.md | 164 +++----- docs/getting-started/self-hosted.md | 26 +- docs/self-hosted-native.md | 19 +- docs/user-guide.md | 215 ++++++---- docs/web/README.md | 11 +- docs/web/architecture.md | 15 +- docs/web/core-connection.md | 15 +- 16 files changed, 712 insertions(+), 834 deletions(-) diff --git a/README.md b/README.md index 9d9b221df..f7f9b4901 100644 --- a/README.md +++ b/README.md @@ -6,73 +6,68 @@ An open-source, self-hosted implementation of the OpenAI Agents API with multiple native harnesses. -[Get started](#quick-start) · [Documentation](#documentation) · [Call the API](docs/getting-started/quickstart.md) · [Contributing](CONTRIBUTING.md) +[Install](#install) · [Call the API](docs/getting-started/quickstart.md) · [Documentation](#documentation) · [Contributing](CONTRIBUTING.md) **English** · [简体中文](README.zh-CN.md) -Choose Codex, Claude Code or MiniMax Code as your execution engine. Sandbox providers, -model providers and harnesses connect through defined protocols and thin adapters, -so you can add or replace components without changing Core orchestration. +## What it is -## Quick start +OpenAgentCore runs AI agents on your own infrastructure behind the OpenAI Agents API. -On a Linux amd64 host with Docker and Python 3.9+, install the latest stable release: +- **Same API as OpenAI.** Point the official OpenAI SDK, or plain HTTP, at your + installation. No new client to learn. +- **Your choice of agent.** Each Session runs a native harness: Codex, Claude Code or + MiniMax Code, with the model provider you configure. +- **Your choice of machine.** Agents work in a managed sandbox (Docker, microsandbox + or E2B), or on your own Linux, macOS or Windows machine. +- **Every part is replaceable.** Sandboxes, harnesses and model providers plug in + through defined protocols. + +## Install + +On a Linux amd64 host with Docker and Python 3.9+: ```sh curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash ``` -You can customize the listen address, ports and deployment settings with these [installation options](docs/getting-started/install-options.md). +Then: -1. [Install Core and Web](docs/getting-started/install.md) on a Linux host. The guide - covers prerequisites, release download, local trials and HTTPS setup. -2. Sign in to Web with the installer-created Core key. Configure a model provider, - create a Project and issue its API key. For managed execution, - [add a node or configure E2B](docs/getting-started/nodes.md). -3. [Run your first Session](docs/getting-started/quickstart.md) with the pinned Python - SDK. The walkthrough checks authentication, submits a task and waits for its result. +1. **Sign in to Web**, the admin console, with the Core key the installer created. +2. **Set a default model** and **issue a Project API key**. +3. **Add execution capacity:** a node, E2B, or your own machine. +4. **[Run your first Session](docs/getting-started/quickstart.md)** with the OpenAI SDK. -To execute on your own Linux, macOS or Windows machine, follow the -[self-hosted Runtime guide](docs/getting-started/self-hosted.md). +The [installation guide](docs/getting-started/install.md) covers each step, HTTPS +and a quick local trial. Listen addresses, ports and other options: [installation options](docs/getting-started/install-options.md). ## How it fits together ![OpenAgentCore architecture](docs/assets/architecture.png) -Core exposes two APIs. Applications use the public **Agents API** (`/v1`), the same -protocol as OpenAI's. Operators use the private **Core API** (`/core/v1`) through -Web. Core manages Sessions and execution state. Runtime prepares Skills and MCP tools, -then runs the selected harness. Sandbox providers manage environments; model providers -serve inference requests. Each connection is a defined protocol, so any component -can be replaced on its own. +Core exposes two APIs: -Managed Providers supply Linux environments. Self-hosted daemons run on Linux, -macOS and Windows, subject to the selected Harness's -[platform support](docs/self-hosted-native.md#platforms-and-prerequisites). The daemon uses -its starting account's permissions; isolation belongs to an outer sandbox. -Releasing an executor does not destroy its Environment. +| API | Path | Used by | +| --- | --- | --- | +| **Agents API** | `/v1` | Your applications. Same protocol as OpenAI's | +| **Core API** | `/core/v1` | Operators, through Web | -See the [coverage record](contracts/agents-api/README.md) for supported API operations -and native harness differences. +Core keeps all state. The Runtime runs the chosen harness inside the Environment. +Each connection is a defined protocol, so any part can be replaced on its own. See +the [architecture guide](docs/architecture.md). ## Documentation -For a complete application example using the Parsar product UI, see -[`example/parsar`](example/parsar/README.md): model, Skill, MCP and runtime management, reusable Agents, and independent -Sessions backed by the public API. - -| Start here | Purpose | +| I want to | Start with | | --- | --- | -| [Documentation index](docs/getting-started/README.md) | Installation, usage and administration reading paths | -| [Architecture](docs/architecture.md) | Components, the three API namespaces and a Session end to end | -| [User guide](docs/user-guide.md) | Sessions, Skills/Plugins/MCP, files, cancellation and recovery | -| [Configuration](docs/configuration.md) | Operator settings and model configuration | -| [API reference](docs/api/README.md) | Application, administration and machine APIs | -| [Developer guide](docs/development.md) | Repository map, local setup, builds and validation | -| [Add a Harness](contracts/agents-api/harness-onboarding.md) | Start with [agent/harness.go](apps/parsar-daemon/internal/agent/harness.go), then adapter implementation and acceptance | -| [Core–Runtime protocol](docs/runtime-protocol.md) | Lifecycle, capability preparation and execution | -| [Add a Sandbox Provider](docs/sandbox-provider.md) | Environment creation and resource ownership | - -Before changing code, read [the contributor rules](CONTRIBUTING.md). +| Install and operate an installation | [Installation](docs/getting-started/install.md), then [operations](docs/getting-started/operations.md) | +| Build an application on the API | [Quickstart](docs/getting-started/quickstart.md), then the [Agents API guide](docs/api/public-agent-api.md) | +| See a complete application | [Examples](docs/examples.md) | +| Run agents on my own machine | [Self-hosted execution](docs/getting-started/self-hosted.md) | +| Understand the design | [Architecture](docs/architecture.md) | +| Add a sandbox, harness or other component | [Developer guide](docs/development.md) | + +All pages: [documentation index](docs/getting-started/README.md). Before changing +code, read the [contributor rules](CONTRIBUTING.md). diff --git a/README.zh-CN.md b/README.zh-CN.md index 79aa707e9..dc403ca68 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -6,62 +6,63 @@ OpenAI Agents API 的开源实现,支持多种原生执行引擎,可部署在自己的基础设施上。 -[快速开始](#快速开始) · [文档](#文档) · [调用 API](docs/getting-started/quickstart.md) · [参与贡献](CONTRIBUTING.md) +[安装](#安装) · [调用 API](docs/getting-started/quickstart.md) · [文档](#文档) · [参与贡献](CONTRIBUTING.md) [English](README.md) · **简体中文** -你可以选择 Codex、Claude Code 或 MiniMax Code 作为执行引擎。沙箱、模型供应商和 -Harness 都通过明确的协议和薄适配层接入,新增或替换组件无需修改 Core 的编排逻辑。 +## 这是什么 -## 快速开始 +OpenAgentCore 在你自己的基础设施上运行 AI Agent,对外提供 OpenAI Agents API。 -在已准备 Docker 和 Python 3.9+ 的 Linux amd64 主机上,一条命令安装最新正式版: +- **与 OpenAI 相同的 API。** 官方 OpenAI SDK 或直接 HTTP 调用,改一下地址即可,无需学习新客户端。 +- **自选 Agent。** 每个 Session 运行一个原生 Harness:Codex、Claude Code 或 MiniMax Code, + 使用你配置的模型供应商。 +- **自选机器。** Agent 可以在托管沙箱(Docker、microsandbox 或 E2B)里工作, + 也可以在你自己的 Linux、macOS 或 Windows 机器上工作。 +- **每个部件都可替换。** 沙箱、Harness 和模型供应商都通过既定协议接入。 + +## 安装 + +在已准备 Docker 和 Python 3.9+ 的 Linux amd64 主机上: ```sh curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash ``` -你可以通过[安装配置选项](docs/getting-started/install-options.md)自定义监听地址、端口和部署方式。 +然后: -1. 在 Linux 主机上[安装 Core 和 Web](docs/getting-started/install.md)。安装指南包含环境要求、 - 发行包下载、本地试用和 HTTPS 配置。 -2. 用安装器生成的 Core key 登录 Web,配置模型提供方,创建 Project 并签发应用 API key。 - 使用托管环境时,先[添加节点或配置 E2B](docs/getting-started/nodes.md)。 -3. 跟随[第一个 Session 示例](docs/getting-started/quickstart.md),安装指定版本的 Python SDK, - 验证访问、提交任务并等待执行结果。 +1. 用安装器生成的 Core key **登录 Web**(管理控制台)。 +2. **设置默认模型**,并**签发 Project API key**。 +3. **添加执行资源**:节点、E2B,或你自己的机器。 +4. 用 OpenAI SDK **[运行第一个 Session](docs/getting-started/quickstart.md)**。 -要在自己的 Linux、macOS 或 Windows 机器上执行任务,请阅读 -[自托管 Runtime 指南](docs/getting-started/self-hosted.md)。 +[安装指南](docs/getting-started/install.md)详细介绍每一步,以及 HTTPS 配置和本地快速试用。监听地址、端口等参数见[安装配置选项](docs/getting-started/install-options.md)。 ## 组件关系 ![OpenAgentCore 架构](docs/assets/architecture.png) -Core 对外提供两组 API:应用调用公开的 **Agents API**(`/v1`),与 OpenAI 协议一致; -管理员通过 Web 调用私有的 **Core API**(`/core/v1`)。Core 管理 Session 和执行状态; -Runtime 准备 Skill 和 MCP 工具并运行所选引擎;沙箱供应商管理运行环境,模型供应商提供推理服务。 -各部件之间都通过既定协议连接,任何一个都可以单独替换。 +Core 对外提供两组 API: -托管 Provider 提供 Linux 环境;自托管 daemon 支持 Linux、macOS 和 Windows, -具体组合见 [Harness 平台支持表](docs/self-hosted-native.md#platforms-and-prerequisites)。 -daemon 使用启动账户的权限,隔离由外层沙箱负责。释放执行器不会销毁 Environment。 +| API | 路径 | 调用方 | +| --- | --- | --- | +| **Agents API** | `/v1` | 你的应用,与 OpenAI 协议一致 | +| **Core API** | `/core/v1` | 管理员,通过 Web 调用 | -已支持的 API 操作和原生引擎差异见[协议覆盖记录](contracts/agents-api/README.md)。 +所有状态都由 Core 保存;Runtime 在 Environment 中运行所选 Harness。各部件之间都通过既定协议连接, +任何一个都可以单独替换。详见[架构说明](docs/architecture.md)。 ## 文档 -| 入口 | 内容 | +| 我想要 | 从这里开始 | | --- | --- | -| [文档目录](docs/getting-started/README.md) | 安装、使用和运维的阅读路径 | -| [架构](docs/architecture.md) | 各组件、三组 API 与一个 Session 的完整流程 | -| [使用指南](docs/user-guide.md) | Session、Skill/Plugin/MCP、文件、取消与恢复 | -| [配置参考](docs/configuration.md) | 部署设置和模型配置 | -| [API 参考](docs/api/README.md) | 应用、管理与机器接口 | -| [开发指南](docs/development.md) | 仓库结构、开发环境、构建与验证 | -| [接入 Harness](contracts/agents-api/harness-onboarding.md) | 适配器实现与验收 | -| [Core–Runtime 协议](docs/runtime-protocol.md) | 生命周期、能力准备与执行 | -| [接入 Sandbox Provider](docs/sandbox-provider.md) | 环境创建与资源管理 | - -修改代码前请阅读[贡献规范](CONTRIBUTING.md)。 +| 安装并运维 | [安装指南](docs/getting-started/install.md),然后看[运维](docs/getting-started/operations.md) | +| 基于 API 开发应用 | [快速开始](docs/getting-started/quickstart.md),然后看 [Agents API 指南](docs/api/public-agent-api.md) | +| 看一个完整的应用 | [示例](docs/examples.md) | +| 在自己的机器上运行 Agent | [自托管执行](docs/getting-started/self-hosted.md) | +| 了解设计 | [架构说明](docs/architecture.md) | +| 接入新的沙箱、Harness 或其他组件 | [开发指南](docs/development.md) | + +全部文档见[文档目录](docs/getting-started/README.md)。修改代码前请阅读[贡献规范](CONTRIBUTING.md)。 diff --git a/docs/architecture.md b/docs/architecture.md index 51f55d306..5b5ad782f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -27,20 +27,10 @@ The diagram has four tiers: ![Three namespaces and their credentials](assets/architecture-api-surfaces.png) -Core serves three namespaces. Each has one kind of caller and its own credential; -a credential used in another namespace gets 401. - -| Namespace | Caller | Credential | Purpose | -| --- | --- | --- | --- | -| Agents API, `/v1` | Applications and the official SDK | Project API key | Exactly the pinned OpenAI Agents API routes. Core-only fields live in `x_agents_core` | -| Core API, `/core/v1` | Core Web's server and operator scripts | Core key | Projects and keys, resource reads and deletion, audit, nodes, metrics and deployment settings | -| Machine API, `/api/v1` | Sandbox nodes and Runtime daemons | Machine credentials issued through `/core/v1` | Node enrollment and connection, Runtime daemon WebSocket | - -The browser never receives the Core key: Web keeps it on its server and forwards -signed-in `/core/v1` requests. The reverse proxy sends `/v1` and `/api/v1` to Core -and everything else to Web. The [API index](api/README.md) owns the complete -route and credential matrix; [design principles](design-principles.md) explain -Projects, keys and administrator authority. +Core serves three namespaces: the Agents API (`/v1`) for applications, the Core +API (`/core/v1`) for operators, and a machine API (`/api/v1`) for nodes and Runtime +daemons. Each has its own credential; one used elsewhere gets 401. The +[API index](api/README.md) owns the full matrix of callers, credentials and routes. ## Core @@ -98,15 +88,12 @@ message order, receipts and failure ownership. ## Boundaries to keep in mind -- **Isolation belongs to the outer Environment.** The daemon runs tools with its - launching user's permissions and adds no filesystem, permission or network - sandbox. Docker, microsandbox or E2B provide managed isolation - ([native Runtime guide](self-hosted-native.md)). +- **Isolation belongs to the outer Environment.** The daemon is not a sandbox + ([Runtime and outer isolation](design-principles.md#runtime-and-outer-isolation)). - **Execution and compute have separate lifetimes.** Closing an executor does not release its allocation, destroy its Environment or delete its workspace. Reclamation is an explicit Sandbox Provider operation. -- **Model keys stay with the compute that owns them.** A deployment default model - provider applies only on operator compute; a self-hosted Session must bring its - own ([model execution](../contracts/agents-api/model-execution.md)). +- **Model keys stay with the compute that owns them.** A self-hosted Session brings + its own model provider ([why](user-guide.md#which-model-provider-a-session-uses)). - **Core Web is an administrator console.** It calls only `/core/v1` and cannot start Sessions or send input ([Web architecture](web/architecture.md)). diff --git a/docs/configuration.md b/docs/configuration.md index 6e98c1c58..31ed857b9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -202,18 +202,20 @@ node's own files can't change its capacity, size or Runtime. ### Default models -Each harness has at most one default model provider: `protocol`, HTTPS `base_url`, -a write-only `api_key` and, for MiniMax Code, `context_window` and -`max_output_tokens`. It is the same bundle as `x_agents_core.model_provider`. Core -encrypts it with `secrets/credential.key` and never returns the key. - -New Core-hosted (`openai_hosted`) Sessions and Sessions without an environment -(`none`) use it when neither the request nor the Agent carries a provider; each -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](getting-started/quickstart.md#model-providers) and the -[model execution contract](../contracts/agents-api/model-execution.md#deployment-defaults). +Each harness has at most one default model configuration: + +- `model`: the provider's model ID; +- `model_provider`: the same bundle as `x_agents_core.model_provider` (`protocol`, + HTTPS `base_url`, write-only `api_key`, and for MiniMax Code `context_window` and + `max_output_tokens`); +- `harness_config`: optional native model parameters, `{}` by default. + +Core encrypts the key with `secrets/credential.key` and never returns it. Set it in +Web or with `PUT /core/v1/harnesses/{harness}/model-configuration`. + +Which Sessions use the default, and in what order it applies, is in +[Which model provider a Session uses](user-guide.md#which-model-provider-a-session-uses). +Full rules: [model execution](../contracts/agents-api/model-execution.md#deployment-defaults). The operator file `AGENTS_API_EXECUTION_OPTIONS_FILE` is retired; see [installation version policy](getting-started/operations.md#installation-version-policy). diff --git a/docs/design-principles.md b/docs/design-principles.md index 4a7107705..47b89af23 100644 --- a/docs/design-principles.md +++ b/docs/design-principles.md @@ -1,100 +1,92 @@ # Core design principles -OpenAgentCore is an open-source implementation of the OpenAI Agents API. Its public -contract follows the repository's pinned upstream baseline; documented native -harness differences remain explicit. Core extensions must not silently change -upstream resource shapes or execution semantics. +OpenAgentCore implements the OpenAI Agents API. Its public contract follows the +repository's pinned upstream baseline. Documented native harness differences stay +explicit; Core extensions never silently change upstream resource shapes or +execution semantics. ## Three namespaces, three credentials -Applications use `/v1` with a Project API key. Administrators use `/core/v1` -with the Core key. Nodes and Runtime daemons use `/api/v1` with their own scoped -machine credentials. The [API index](api/README.md) owns the complete caller, -credential and route matrix. +Applications, administrators and machines each use their own namespace and +credential. The [API index](api/README.md) owns the complete matrix. -Web calls the management API through its server and keeps the Core key there. -Signing in grants administrator access to that deployment; it does not create -an application Session or give the browser a Project API key. - -This is a separation of API authority, not a claim that a deployment administrator -cannot possess application credentials. An administrator can issue an API key and -use it separately. The console itself has no impersonation or execution operation. -API-key plaintext is returned once on issuance, never on reads. +Separating API authority does not stop an administrator from holding application +credentials: they can issue a Project API key and use it like any application. ## Projects own assets -A Project owns one execution tenant and its assets. Multiple named API keys belong -to the Project and share its principal, permissions and resources. Each write keeps -its actual key identity for provenance. There are no Core users, roles, memberships -or read-only keys. Names are labels; stable IDs identify Projects and keys. - -Projects and application API keys live only in PostgreSQL. The console and -management API use the same records. Configuration contains deployment settings, -not application credentials or Project definitions. Issue a new key in the same -Project and revoke the previous one to rotate credentials. Revocation affects only -that key and preserves assets, provenance and accepted execution. Explicit Project -archive revokes every key and blocks new issuance in that Project. -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](../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. - -## Resource isolation and administrator authority - -Agent API reads, writes and references are scoped to the authenticated key's Project. -A foreign resource remains indistinguishable from an absent resource under the -existing public operation's rules. Deployment nodes, configured model endpoints -and startup settings are deployment infrastructure, not shared business assets. - -Administrators can inspect resources and execution history, delete resources under -the same rules as their public deletion operations, manage Projects and API keys, -issue node enrollment tokens and self-hosted executor credentials, and query -operational counts and usage. They cannot use management endpoints to -create, copy or edit arbitrary assets, start a Session, send an event, cancel -work, or read stored credentials. Project keys share all assets within their -Project; nothing is shared or copied across Projects. +A Project owns one execution tenant and its assets. + +- **Keys.** A Project has one or more named API keys. They share its principal, + permissions and resources. Each write records the key that made it. +- **No users or roles.** Core has no users, roles, memberships or read-only keys. + Names are labels; stable IDs identify Projects and keys. +- **Storage.** Projects and keys live only in PostgreSQL, never in deployment + configuration. A key's plaintext is returned once, at issuance. +- **Rotation.** Issue a new key in the same Project, then revoke the old one. + Revoking a key keeps assets, provenance and accepted work. +- **Archive.** Archiving a Project revokes every key and blocks new ones. + Administrators can still inspect and delete its resources. + +The Core key is a deployment credential, managed separately; see +[Core key](getting-started/operations.md#core-key). Product concepts such as users, +workspaces and business permissions stay outside Core: +a product like Parsar is an ordinary API-key holder in a Project. + +## Resource isolation + +Agents API reads, writes and references are scoped to the key's Project. A resource +in another Project is indistinguishable from an absent one. Nothing is shared or +copied across Projects. Nodes, configured model endpoints and startup settings are +deployment infrastructure, not business assets. + +## What administrators can and cannot do + +| Administrators can | Administrators cannot | +| --- | --- | +| Inspect resources and execution history | Create, copy or edit arbitrary assets | +| Delete resources, under the public deletion rules | Start a Session, send input or cancel work | +| Manage Projects and API keys | Read stored credentials | +| Issue node enrollment tokens and executor credentials | Impersonate an application | +| Query operational counts and usage | | + +Web signs in with the Core key and keeps it on its server; signing in never creates +a Session or gives the browser a Project API key. ## Runtime and outer isolation -The same daemon and Core protocol serve self-hosted Linux, macOS and Windows. -OS differences belong to Runtime implementations; harness differences belong to -adapters. Managed Providers remain Linux-only. Runtime prepares capabilities and -executes work; Providers create, bootstrap and reclaim outer Environments. - -The daemon runs tools with its launching user's permissions. It does not add a -filesystem, permission or network sandbox, including on Linux. Outer Docker/E2B/ -microsandbox Environments provide managed isolation. Credential authentication, -ordinary private storage, atomic writes, locks and process cleanup remain required, -but do not protect Runtime data from tools running as the same user. Local -capability snapshots share the managed parser and do not create a second security -boundary. See the [native Runtime guide](self-hosted-native.md) for current platform -validation limits. - -## Secrets and evidence - -Credential values, model credentials and confidential template initialization are -write-only through resource APIs, including administrator reads. Public metadata -projections are reused by the management API. This does not redact arbitrary -user-authored conversation text, Skill source or Artifact content: administrators -who inspect those records see their recorded contents. - -Public writes retain their actual API-key provenance. Administrator writes retain -a separate audit identity and target Project. The console's fixed actor label is -display-only; Core trusts the Core key, not that forwarded label. Audit failure rolls -back the business transaction. Reads are not audited. Resources from the removed -copy operation keep their `admin_copy` ownership, distinct from historical unknown -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](../CONTRIBUTING.md) and -[Core–Runtime protocol](runtime-protocol.md) 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 +The same daemon and protocol serve self-hosted Linux, macOS and Windows. OS +differences belong to Runtime implementations; harness differences belong to +adapters. Managed Providers are Linux-only. + +**The daemon is not a sandbox.** It runs tools with its launching user's +permissions and adds no filesystem, permission or network isolation, on any OS. +Isolation comes from the outer Environment: Docker, E2B or microsandbox for managed +Sessions, or whatever container or VM you choose for a self-hosted machine. +Authentication, private storage, locks and process cleanup still apply, but they do +not protect Runtime data from tools running as the same user. + +## Secrets and audit + +- **Write-only secrets.** Credential values, model keys and confidential template + data are never returned by any read, including administrator reads. Conversation + text, Skill source and Artifact content are not secrets: administrators see them. +- **Provenance.** Public writes record their API key. Administrator writes record a + separate audit identity and the target Project. Web's actor label is display-only; + Core trusts the Core key, not the label. +- **Audit is transactional.** An audit failure rolls back the write. Reads are not + audited. Audit records never contain request bodies, secrets or file contents. +- **History.** Resources from the removed copy operation keep their `admin_copy` + ownership, distinct from historical unknown ownership. + +## Out of scope + +Do not add product users, RBAC, cross-Project shared assets, administrator +execution or compatibility with old private protocols. Implementers follow the +[contributor rules](../CONTRIBUTING.md) and the +[Core–Runtime protocol](runtime-protocol.md). + +Native failure classification is adapter-owned and uses finite, structured native +values. Optional Runtime error metadata is normalized once; it never replaces Core's +terminal authority, cancellation receipts, Usage or native identity. See [native failure classification](../contracts/agents-api/native-error-classification.md). diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index c8c27f5dd..86410c65d 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -1,39 +1,38 @@ # OpenAgentCore documentation -Start with the path that matches your role. These pages are the canonical sources -for the documentation website; generated site pages are not a second manual. +OpenAgentCore runs AI agents on your own infrastructure behind the OpenAI Agents +API. Pick the path that matches your role. New here? Read the +[architecture overview](../architecture.md) first. -## First installation and first task +## Operators: install and run -1. [Install Core and Web](install.md), then sign in with the Core key. -2. [Add managed execution capacity](nodes.md) or - [connect your own Runtime](self-hosted.md). -3. Issue a Project API key and follow the [first Session walkthrough](quickstart.md). -4. Continue with the [user guide](../user-guide.md) for capabilities, files and recovery. +1. [Install Core and Web](install.md) and sign in. +2. Add execution capacity: [managed nodes or E2B](nodes.md), or + [your own machine](self-hosted.md). +3. Issue a Project API key and hand it to the application developer. -## Operate a deployment +| Guide | Covers | +| --- | --- | +| [Installation](install.md) | Prerequisites, HTTPS, first sign-in, advanced options | +| [Configuration](../configuration.md) | `config.json`, default models, sandbox deployment | +| [Nodes](nodes.md) | Adding, checking and removing managed nodes | +| [Self-hosted execution](self-hosted.md) | Connecting your own machine to a Session | +| [Native Runtime](../self-hosted-native.md) | Platforms, installing and operating `oac-daemon` | +| [Operations](operations.md) | Services, backups, keys, repair and troubleshooting | +| [Web console](../web/README.md) | What the console shows and manages | + +## Application developers: build on the API -| Guide | Use it for | +| Guide | Covers | | --- | --- | -| [Installation](install.md) | Host prerequisites, release bundles, HTTPS and first sign-in | -| [Configuration](../configuration.md) | Installer configuration and database-owned settings | -| [Nodes](nodes.md) | Managed capacity, readiness and removal | -| [Self-hosted execution](self-hosted.md) | Connecting a user-owned machine to a Session | -| [Native daemon](../self-hosted-native.md) | Platform support and local installation lifecycle | -| [Operations](operations.md) | Service lifecycle, backups, keys, repair and troubleshooting | -| [Administrator console](../web/README.md) | Monitoring and managing Core through Web | - -## Build an application - -The [user guide](../user-guide.md) connects common tasks to their detailed contracts. -The [API index](../api/README.md) identifies each caller and credential. Use the -[coverage record](../../contracts/agents-api/README.md) to check operation support -and Harness differences before relying on an optional feature. - -## Extend Core - -Start with the [developer guide](../development.md). It links the repository map, -required checks and extension points for Harness adapters, Runtime implementations -and Sandbox Providers. Architecture rules live in -[CONTRIBUTING.md](../../CONTRIBUTING.md); distribution and release procedures live in -[the maintainer guide](../maintainers.md). +| [Quickstart](quickstart.md) | From a Project API key to a finished Session | +| [User guide](../user-guide.md) | Common tasks: harness and model choice, follow-ups, capabilities, files, cancel | +| [Agents API guide](../api/public-agent-api.md) | Every resource, with SDK and HTTP examples | +| [Examples](../examples.md) | Complete applications built on the API | +| [API index](../api/README.md) | All three namespaces and their credentials | + +## Contributors: extend Core + +Start with the [developer guide](../development.md): repository map, local setup, +and how to add a Sandbox Provider, a harness or a Runtime feature. Repository rules +are in [CONTRIBUTING.md](../../CONTRIBUTING.md). diff --git a/docs/getting-started/install.md b/docs/getting-started/install.md index e29a36fcc..cfe5aa85a 100644 --- a/docs/getting-started/install.md +++ b/docs/getting-started/install.md @@ -1,20 +1,21 @@ # Install Core and Web One command installs Core, the Web console and PostgreSQL on a Linux host. Web is -the administrator console: you sign in with the Core key, issue Project API keys and -add nodes. Applications call Core's API with those keys. +the administrator console: you sign in with the Core key, issue Project API keys +and add nodes. Applications then call Core's API with those keys. + +The default path has five steps: 1. [Check the prerequisites](#prerequisites). -2. [Download a release bundle](#download-a-release). -3. [Run the installer](#install). -4. [Put Core and Web behind HTTPS](#https-and-the-reverse-proxy), or - [try it locally first](#try-it-locally-with-a-quick-tunnel). -5. [Sign in to Web and issue a key](#sign-in-to-web). -6. [Add a node](nodes.md). +2. [Run the installer](#install). +3. [Make Core reachable](#make-core-reachable) over HTTPS, or through a quick tunnel + for a trial. +4. [Sign in to Web](#sign-in-to-web), set a default model and issue a key. +5. [Add execution capacity](#next-steps): a node, E2B or your own machine. -These pages describe the current source. Every bundle carries the docs that match it -under `docs/`. Core supports fresh installation and repair of the -same release; historical-version upgrades and conversion are unsupported. +Every flag, listener addresses and ports are in +[installation options](install-options.md). Offline hosts, other sandbox backends +and split deployments are in [Advanced installation](#advanced-installation). ## Prerequisites @@ -22,160 +23,288 @@ same release; historical-version upgrades and conversion are unsupported. - Linux amd64 with Python 3.9 or newer. - Docker Engine with Docker Compose 2.26.0 or newer (`docker compose version`). -- An account that can run `docker` and write to the installation directory. Both - ordinary users and root are supported; the installer uses the current account - without invoking sudo, switching accounts or changing Docker permissions. +- An account that can run `docker` and write to its home directory. Ordinary users + and root both work; the installer never calls sudo. - Free loopback ports 8091 (Core) and 8080 (Web), or [custom listeners](install-options.md#listeners-and-access). -- curl to fetch the installation script; no GitHub CLI or login is required. +- curl. No GitHub CLI or login is needed. + +The Core host needs no KVM. + +**A public HTTPS address**, such as `https://core.example`, with a DNS name and a +TLS certificate. Nodes, E2B sandboxes and self-hosted machines reach Core there. A +local trial can skip it and [set it later](#make-core-reachable). + +## Install + +```sh +curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash +``` -The Core host needs no KVM and no systemd user services, unless you choose -[native Core](#native-core). +For an HTTPS deployment, pass the public address: -**Network, for nodes and remote access** +```sh +curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash -s -- --public-url https://core.example +``` -- A DNS name for Core and Web, such as `core.example`, with a TLS certificate. -- A reverse proxy on the Core host that sends three routes to the right service; see - [HTTPS and the reverse proxy](#https-and-the-reverse-proxy). +The script picks the latest stable release, verifies its checksum and runs the +bundled installer, which: -Node hosts and their sandboxes, E2B sandboxes and self-hosted executors all reach -Core at this HTTPS address. A local trial needs none of this: install without a -public URL and set it later. +1. checks the host and loads the Core, Web and PostgreSQL images; +2. creates `~/.oac/core` (mode `0700`) with the Core key, `config.json` and the + `oac` management command; +3. starts PostgreSQL, Core and Web with Docker Compose, on their configured listeners + (loopback by default); +4. selects the microsandbox backend at the Standard size. It adds no node. -## Download a release +It creates no Project or key and makes no model request. It ends by printing the +console address, the API base URL and the next steps. -Every Release includes a standalone [install.sh](https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh). -It selects the latest published stable release by default, downloads that release's -control-plane bundle and checksum, verifies the archive, and runs its bundled installer. -This installs Core, Web and PostgreSQL without downloading Runtime images or node -execution files. Nodes download those separately when they are added. -You do not need to find a tag, commit SHA or archive filename. +Without `--public-url`, only this host can reach the installation: by default Web at +`http://127.0.0.1:8080` and the API at `http://127.0.0.1:8091/v1`. To listen on other +addresses or ports, see [installation options](install-options.md#listeners-and-access). -## Install +## Make Core reachable -Install the latest stable release: +Nodes, E2B and self-hosted machines need a public HTTPS address. Choose one: + +| Option | Use it for | +| --- | --- | +| [HTTPS and the reverse proxy](#https-and-the-reverse-proxy) | Any lasting installation | +| [A quick tunnel](#try-it-locally-with-a-quick-tunnel) | A trial without DNS or certificates | + +Then set the address, if you didn't pass `--public-url`: ```sh -curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash +# in ~/.oac/core/config.json: "public_url": "https://core.example" +~/.oac/core/oac apply ``` -For an HTTPS deployment, pass the public address: +Core derives every address it hands out from `public_url`. To change it later, see +[Changing the public URL](../configuration.md#changing-the-public-url). + +### HTTPS and the reverse proxy + +Core and Web share one public origin. Your reverse proxy terminates TLS and routes +by path: + +| Path | Goes to | Callers | +| --- | --- | --- | +| `/v1`, `/v1/*` | Core, `127.0.0.1:8091` by default | Applications, with a Project API key | +| `/api/v1/*` | Core, `127.0.0.1:8091` | Nodes, sandboxes and self-hosted machines. Uses WebSockets | +| Everything else | Web, `127.0.0.1:8080` by default | Browsers, and node installers at `/node-install/*` | + +The proxy must: + +- **Preserve Host.** Web accepts only the host of its public URL. +- **Pass WebSocket upgrades** on `/api/v1`. +- **Not buffer or time out streams.** `/v1` streams Session events. +- **Accept large uploads.** Source files may reach 512 MiB; Core enforces the limits. + +Run the proxy on the Core host when Core and Web listen on loopback (the default). +`oac status` prints these routes with your addresses and ports. + +**Caddy** obtains the certificate itself and passes Host and WebSockets by default: + +```caddyfile +core.example { + @core path /v1 /v1/* /api/v1/* + handle @core { + reverse_proxy 127.0.0.1:8091 + } + handle { + reverse_proxy 127.0.0.1:8080 + } +} +``` + +**nginx**, for example in `/etc/nginx/conf.d/oac.conf` inside the `http` block: + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + server_name core.example; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name core.example; + ssl_certificate /etc/letsencrypt/live/core.example/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/core.example/privkey.pem; + + client_max_body_size 0; # Core enforces its own upload limits + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_buffering off; # server-sent events on /v1 + proxy_request_buffering off; + proxy_read_timeout 1h; # long-lived WebSockets and streams + proxy_send_timeout 1h; + + location = /v1 { proxy_pass http://127.0.0.1:8091; } + location /v1/ { proxy_pass http://127.0.0.1:8091; } + location /api/v1/ { proxy_pass http://127.0.0.1:8091; } + location / { proxy_pass http://127.0.0.1:8080; } +} +``` + +Check the routing: ```sh -curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash -s -- --public-url https://core.example +curl -s -o /dev/null -w '%{http_code}\n' -H 'OpenAI-Beta: agents=v1' https://core.example/v1/agents +``` + +`401` means `/v1` reached Core, which asks for a key. `404` means it reached Web: +fix the proxy, or application calls and every node connection will fail. + +TLS verification stays on everywhere. With a private certificate authority, node +hosts, self-hosted machines and the Runtime image must trust it. + +### Try it locally with a quick tunnel + +A [Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) +gives a trial installation a temporary public HTTPS address. It forwards to one +port, so put a local proxy with the same routes in front: + +```caddyfile +http://:8443 { + bind 127.0.0.1 + @core path /v1 /v1/* /api/v1/* + handle @core { + reverse_proxy 127.0.0.1:8091 + } + handle { + reverse_proxy 127.0.0.1:8080 + } +} ``` -To select a version, add `--version v1.2.3` after `bash -s --`. Explicit versions -may include prereleases; the default never selects one. Other arguments go unchanged -to the bundled installer. You can also download `install.sh` from the Release page -and run `bash install.sh --version v1.2.3`. The examples below use this saved script -or the bundle's existing `./install.sh`. +1. Start the proxy: `caddy run --config Caddyfile`. +2. Start the tunnel: `cloudflared tunnel --url http://127.0.0.1:8443`. It prints an + address such as `https://random-words.trycloudflare.com`. +3. Set that address as `public_url` in `~/.oac/core/config.json` and run + `~/.oac/core/oac apply`. -The downloader resolves the release once, verifies SHA-256 before extraction, and -retains the verified bundle under `~/.oac/releases/` for repair. It never replaces -an existing installation or upgrades it. To repair an installed version, select -that same version explicitly. The bundled installer also checks its own -`SHA256SUMS` before changing installation state. +The address changes whenever `cloudflared` restarts; nodes bound to the old address +must then be added again. Throughput is low, so a node's first Runtime download +(about 500 MB) can be slow; see [slow links](nodes.md#rerun-expiry-and-slow-links). -For machines without GitHub access, transfer the Release's -`*-linux-amd64-offline.tar.gz` and matching `.sha256` file, verify and extract -them locally, then run the bundled `./install.sh`. This explicitly includes node and -Runtime files so Web can serve them without release access. The default online -installation uses the smaller archive and leaves those downloads to the nodes. +## Sign in to Web -The installer prints each stage before it starts, including image preparation and -service startup. Its final summary groups access addresses, sign-in details, -next steps and management commands. Colors are enabled only in a terminal; set -`NO_COLOR=1` to disable them. Redirected output stays plain text. A failed step -stops installation and never prints a successful completion message. A no-change -repair checks installation settings without rechecking health; use `oac status` -to inspect service health. +1. **Open the console** at the address the installer printed: your public URL, or + `http://127.0.0.1:8080` on the Core host by default. Web refuses other host names. + For a remote host without a public URL, forward the port over SSH first, for + example `ssh -L 8080:127.0.0.1:8080 `. +2. **Sign in with the Core key**, the installation's administrator credential. Web has + no user accounts. See [Core key](operations.md#core-key). -The installer: + ```sh + cat ~/.oac/core/secrets/core.key + ``` -1. checks the host and the bundle, and loads the Core, Web and PostgreSQL images; -2. creates private `~/.oac` (mode `0700`) and the installation directory `~/.oac/core` with the Core key, `config.json` - and the `oac` command ([what it creates](#what-the-installer-creates)); -3. starts PostgreSQL, Core and Web with Docker Compose, on loopback ports only; -4. selects microsandbox at Web's Standard size (2 CPUs, 4 GiB memory and two 8 GiB - disks each). It adds no node, so this host needs no KVM; you add nodes in Web. +3. **Set a default model.** On **System**, find **Default model**. On the card marked + **Default** (Codex unless you changed it), choose **Set** and enter the model and + its provider's base URL and API key. MiniMax Code also needs the context window + and max output tokens. See [Default models](../configuration.md#default-models). +4. **Create a project and issue a key.** On **Projects and keys**, choose + **Create project**, then **Issue key**. The dialog shows the key once: copy it and + keep it safe. Its **How to call** card shows the API base URL and sample requests. +5. **Hand over** the key and the API base URL to the application developer. They continue with the [quickstart](quickstart.md). -It creates no Project or API key, makes no model request and runs no sample task. -It ends by printing the console address, the API base URL and the next steps. +Web's **Overview** tracks these steps in a **Getting started** checklist. -Without `--public-url`, the installation uses its configured loopback addresses. -See [listener configuration](install-options.md#listeners-and-access). Set -`public_url` in `config.json` later and run `oac apply`; you don't reinstall. Nodes, -E2B and self-hosted executors need the public URL. +## Next steps -### Installation choices +| Goal | Guide | +| --- | --- | +| Run Sessions in managed sandboxes | [Add a node](nodes.md), or use [E2B](#sandbox-backend) | +| Run your first Session | [Quickstart](quickstart.md) | +| Run Sessions on your own machine | [Self-hosted execution](self-hosted.md) | +| Operate the installation | [Operations](operations.md) and [configuration](../configuration.md) | -For flags, listener addresses and custom ports, see [Installation options](install-options.md). +## Advanced installation -#### Sandbox backend +### Installer options + +Every flag, with the `config.json` field it seeds, is in +[installation options](install-options.md). Pass them after `bash -s --`, or +download `install.sh` from the Release page and run it directly. The script +verifies the bundle's SHA-256 before extracting it and keeps the verified bundle +under `~/.oac/releases/` for repair. It never upgrades an existing installation. + +**Offline hosts.** Transfer the Release's `*-linux-amd64-offline.tar.gz` and its +`.sha256` file, verify and extract them, then run the bundled `./install.sh`. The +offline bundle also carries the node and Runtime files, so Web can serve them to +nodes without release access. + +**Output.** The installer prints each stage, then a summary of addresses, sign-in +details and next steps. Set `NO_COLOR=1` to disable colors. A failed step stops +installation without a success message. + +### Sandbox backend A deployment runs its sandboxes on exactly one backend: | `--sandbox` | Sandboxes run on | You then | | --- | --- | --- | -| `microsandbox` (default) | microVMs on your nodes (KVM), 2 CPUs, 4 GiB memory and two 8 GiB disks each | [Add nodes](nodes.md) in Web | -| `docker` | Docker on your nodes, 2 CPUs and 2 GiB each; weaker isolation, confirmed at install | [Add nodes](nodes.md) in Web | -| `e2b` | E2B's cloud, with the CPU and memory of your template build | Nothing: E2B needs no nodes | -| `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`](../../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 -running, and you choose the backend on the Nodes page. - -`--sandbox docker` first prints Docker's drawbacks. Containers share the host kernel, -so a container escape reaches the node host, while microsandbox runs each sandbox in -its own microVM. The node service account in the `docker` group is root-equivalent -on each node host. Choose Docker only for trusted workloads or hosts without KVM. -The installer then asks for confirmation, defaulting to No; without a terminal, pass -`--accept-docker-risks`. Unconfirmed, it exits with an error before it installs -anything. - -E2B also needs an HTTPS public URL that is not loopback, because E2B's sandboxes -call Core from E2B's cloud. The installer refuses `--sandbox e2b` without one, before -it installs anything: +| `microsandbox` (default) | microVMs on your nodes (KVM): 2 CPUs, 4 GiB memory and two 8 GiB disks each | [Add nodes](nodes.md) in Web | +| `docker` | Docker on your nodes: 2 CPUs and 2 GiB each; weaker isolation | [Add nodes](nodes.md) in Web | +| `e2b` | E2B's cloud, sized by your template build | Nothing: E2B needs no nodes | +| `none` | Nothing yet | Choose on the **Nodes** page in Web | + +The Standard sizes come from Web's +[`standard-sizes.json`](../../apps/web/src/features/sandbox/standard-sizes.json). If +Core refuses the choice, for example because E2B rejects the key, the installer +prints Core's message and exits; the services keep running and you choose the +backend in Web. To change the backend or size later, see +[Sandbox deployment](../configuration.md#sandbox-deployment). + +**Docker's risks.** Containers share the host kernel, so a container escape reaches +the node host; microsandbox gives each sandbox its own microVM. The node's service +account in the `docker` group is root-equivalent. Choose Docker only for trusted +workloads or hosts without KVM. The installer asks for confirmation (default No); +without a terminal, pass `--accept-docker-risks`. + +**E2B** needs a public HTTPS URL that is not loopback, because E2B's sandboxes call +Core from E2B's cloud. Prepare the template build with the +[E2B guide](../../services/agents-api/deploy/e2b/README.md), then: ```sh ./install.sh --public-url https://core.example --sandbox e2b \ --e2b-api-key-file "$HOME/.oac/e2b-api-key" --e2b-template ':' ``` -Prepare the template build with the -[E2B guide](../../services/agents-api/deploy/e2b/README.md). To change the backend or -the sandbox size later, use the Nodes page in Web; see -[Nodes](nodes.md#change-the-sandbox-backend-or-size). - -#### Modes +### Modes | Mode | Runs | Use it for | | --- | --- | --- | | all (default) | PostgreSQL, Core and Web | Most installations | -| `--core-only` | PostgreSQL and Core | A Core whose Web runs on another host, or scripts only. Without Web there is no Add node command | +| `--core-only` | PostgreSQL and Core | A Core whose Web runs elsewhere, or scripts only. No Add node command | | `--web-only` | Web | A second host for the console, paired with an existing Core | -A Web-only console forwards every signed-in `/core/v1` request to its Core with the -Core key, so `--core-url` must reach Core's `/core/v1` directly. The default reverse -proxy sends `/core/v1` to Web, so the Core's public URL doesn't work here: +The mode and native Core are fixed once installed; to change them, install into a +new directory. + +A Web-only console forwards signed-in `/core/v1` requests to its Core with the Core +key, so `--core-url` must reach Core's `/core/v1` directly. The public URL doesn't, +because the default proxy sends `/core/v1` to Web: -- **Web on the Core host:** use Core's loopback port, - `--core-url http://127.0.0.1:8091`. -- **Web on another host:** give Core a second HTTPS name whose proxy sends every path to - Core, such as `https://core-api.example` to `127.0.0.1:8091` on the Core host, and use - it as `--core-url`. Allow only the Web host's address on that name; anyone else who - reaches it still needs the Core key. +- **Web on the Core host:** use `--core-url http://127.0.0.1:8091`. +- **Web on another host:** give Core a second HTTPS name that sends every path to + Core, such as `https://core-api.example`, and allow only the Web host's address. -##### Split deployment +#### Split deployment | Host | Install | Reverse proxy | | --- | --- | --- | -| Core | `./install.sh --core-only --public-url https://core.example` | `core.example`: `/v1`, `/v1/*` and `/api/v1/*` to Core; `/node-install/*` to the Web host, with Host rewritten to `console.example`; nothing else. `core-api.example`: every path to Core, for the Web host's address only | +| Core | `./install.sh --core-only --public-url https://core.example` | `core.example`: `/v1`, `/v1/*` and `/api/v1/*` to Core; `/node-install/*` to the Web host with Host rewritten to `console.example`; nothing else. `core-api.example`: every path to Core, for the Web host's address only | | Web | `./install.sh --web-only …`, below | `console.example`: every path to Web | ```sh @@ -185,16 +314,13 @@ proxy sends `/core/v1` to Web, so the Core's public URL doesn't work here: --core-key-file "$HOME/core.key" ``` -Browsers use `console.example`, and nodes download their installer from it. -Applications, nodes and sandboxes call Core at `core.example`, and self-hosted -executors download their installer from there too, which is why `core.example` sends -`/node-install/*` to the Web host. Web serves those files only for its own name, so the -proxy rewrites Host. Web serves bootstrap metadata and any locally available node -artifacts. Missing artifacts redirect to the matching release and download directly -on the node; the Web host does not fetch the Runtime image. For disconnected nodes, -install Web from the offline bundle (or add its verified `artifacts/`). +Browsers and node installers use `console.example`. Applications, nodes, sandboxes +and self-hosted machines call Core at `core.example`; self-hosted machines also +download their installer there, which is why `core.example` forwards +`/node-install/*` to Web. Missing node artifacts redirect to the release; for +disconnected nodes, install Web from the offline bundle. -Caddy on the Core host, where `203.0.113.10` stands for the Web host's address: +Caddy on the Core host, where `203.0.113.10` is the Web host's address: ```caddyfile core.example { @@ -277,198 +403,20 @@ server { The Web host's proxy sends every path to Web, for example `console.example { reverse_proxy 127.0.0.1:8080 }` in Caddy. -Copy the key file from the Core host's `secrets/core.key` with mode `0600`; the -installer keeps its own copy in `secrets/core.key`, so delete `$HOME/core.key` -afterwards. After the Core key is rotated, copy the new key again; see -[Rotate the Core key](operations.md#rotate-the-core-key). A Web-only install selects no -sandbox backend: the Core host's `--sandbox` does, or later the paired console's -**Nodes** page. - -The mode and native Core are fixed once installed. To change them, install into a -new directory. - -#### Native Core - -`--native-core` runs Core as a systemd user service of the installing user; -PostgreSQL and Web stay in containers. It needs a running systemd user manager and -lingering for that user (`sudo loginctl enable-linger "$USER"`), and the bundle's -native binaries must load on the host. PostgreSQL then listens on a loopback port -the installer picks (`ports.database`), and Web uses the host network. Native Core -needs no KVM and is unrelated to the sandbox backend. - -## HTTPS and the reverse proxy - -By default, Core and Web share one public origin; for Web on its own host, see the -[split deployment](#split-deployment). Your reverse proxy terminates TLS and routes by -path: - -| Path | Goes to | Callers | -| --- | --- | --- | -| `/v1`, `/v1/*` | Core, `127.0.0.1:8091` | Applications, with a Project API key | -| `/api/v1/*` | Core, `127.0.0.1:8091` | Nodes, sandboxes and self-hosted executors, with their own machine credentials. Uses WebSockets | -| Everything else | Web, `127.0.0.1:8080` | Browsers: the console, its sign-in and `/core/v1/*`. Node and executor hosts download their installers from `/node-install/*` | - -The proxy must: - -- **Preserve Host.** Web accepts only requests for the host of its public URL. -- **Pass WebSocket upgrades** on `/api/v1`. Nodes and Runtime daemons hold long-lived - WebSocket connections. -- **Not buffer or time out streams.** `/v1` streams Session events (server-sent events). -- **Accept large uploads.** Core enforces its own limits; source files may reach - 512 MiB. - -Web answers 404 on `/v1` and `/api/v1` and never forwards them. If those paths reach -Web, application calls, node enrollment and every sandbox connection fail. Run the -proxy on the Core host, since Core and Web listen on loopback. `oac status` prints -the routes with this installation's ports. - -**Caddy** (obtains and renews the certificate itself; passes Host and WebSockets by -default): - -```caddyfile -core.example { - @core path /v1 /v1/* /api/v1/* - handle @core { - reverse_proxy 127.0.0.1:8091 - } - handle { - reverse_proxy 127.0.0.1:8080 - } -} -``` - -**nginx** (for example `/etc/nginx/conf.d/oac.conf`, inside the `http` block; -use your certificate paths): - -```nginx -map $http_upgrade $connection_upgrade { - default upgrade; - '' close; -} - -server { - listen 80; - server_name core.example; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - server_name core.example; - ssl_certificate /etc/letsencrypt/live/core.example/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/core.example/privkey.pem; - - client_max_body_size 0; # Core enforces its own upload limits - proxy_http_version 1.1; - proxy_set_header Host $http_host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_buffering off; # server-sent events on /v1 - proxy_request_buffering off; - proxy_read_timeout 1h; # long-lived WebSockets and streams - proxy_send_timeout 1h; - - location = /v1 { proxy_pass http://127.0.0.1:8091; } - location /v1/ { proxy_pass http://127.0.0.1:8091; } - location /api/v1/ { proxy_pass http://127.0.0.1:8091; } - location / { proxy_pass http://127.0.0.1:8080; } -} -``` - -Replace `core.example` and, if you changed them, the ports. To check the routing: - -```sh -curl -s -o /dev/null -w '%{http_code}\n' -H 'OpenAI-Beta: agents=v1' https://core.example/v1/agents -``` - -`401` means `/v1` reached Core, which asks for a key; `404` means it reached Web. - -Install with `--public-url https://core.example`, or, for an existing installation, -set `public_url` in `~/.oac/core/config.json` and run `~/.oac/core/oac apply`. -Core derives every address it hands out from this one setting. If you change it while -nodes, sandboxes or self-hosted executors use the old address, `oac apply` lists -them and asks you to confirm; those nodes must then be added again. See -[Changing the public URL](../configuration.md#changing-the-public-url). - -TLS verification stays on everywhere. With a private certificate authority, node -hosts, executor hosts and the Runtime image must trust it. - -## Try it locally with a quick tunnel - -For a trial without DNS or certificates, a -[Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) -gives the installation a temporary public HTTPS address. It forwards to one local -port, so put a plain-HTTP proxy with the same three routes in front, for example this -Caddyfile on `127.0.0.1:8443`: - -```caddyfile -http://:8443 { - bind 127.0.0.1 - @core path /v1 /v1/* /api/v1/* - handle @core { - reverse_proxy 127.0.0.1:8091 - } - handle { - reverse_proxy 127.0.0.1:8080 - } -} -``` +Copy `secrets/core.key` from the Core host with mode `0600`, then delete +`$HOME/core.key`; the installer keeps its own copy. After a +[Core key rotation](operations.md#rotate-the-core-key), copy it again. A Web-only +install selects no sandbox backend. -1. Install, with or without a public URL (`./install.sh`). -2. Start the local proxy: `caddy run --config Caddyfile`. -3. Start the tunnel: `cloudflared tunnel --url http://127.0.0.1:8443`. It prints an - address such as `https://random-words.trycloudflare.com`. -4. Set `"public_url": "https://random-words.trycloudflare.com"` in - `~/.oac/core/config.json` and run `~/.oac/core/oac apply`. -5. Open that address and [sign in](#sign-in-to-web). +### Native Core -A quick tunnel is for trials only. Its address changes whenever `cloudflared` -restarts; nodes and executors bound to the old address must then be added again. -Its throughput is low, so the first node download of the Runtime (about 500 MB) can -be slow; see [slow links](nodes.md#rerun-expiry-and-slow-links). Nodes and E2B need a -reachable HTTPS address, so a loopback-only installation can't have nodes: Web says so -at Add node. +`--native-core` runs Core as a systemd user service; PostgreSQL and Web stay in +containers. It needs a running systemd user manager with lingering +(`sudo loginctl enable-linger "$USER"`), and the bundle's native binaries must load +on the host. PostgreSQL then listens on a loopback port the installer picks +(`ports.database`). Native Core is unrelated to the sandbox backend. -## Sign in to Web - -1. Open the console address the installer printed. Use exactly that address; Web - refuses other host names. For a loopback installation on a remote machine, - forward the configured address and port through SSH first. -2. Sign in with the Core key: - - ```sh - cat ~/.oac/core/secrets/core.key - ``` - - The Core key is the installation's administrator credential. Keep it private; see - [Core key](operations.md#core-key). Web has no user accounts. -3. **Set a default model.** Open **System** and find **Default model**. On the harness - card marked **Default** (Codex unless you changed `core.default_harness`), choose - **Set**; once a provider is configured, the button reads **Replace**. Enter the - model provider's base URL and API key; MiniMax Code also needs the context window - and max output tokens. Core encrypts the key and never shows it again. The default - applies to Core-hosted Sessions and Sessions without an environment when the request - and the Agent carry no model provider; self-hosted Sessions never use it. See - [model providers](quickstart.md#model-providers). -4. **Create a project and issue a key.** Open **Projects and keys**, choose - **Create project** and give it a **Name**, then **Issue key** in it with a - **Key name**. The **Key issued** dialog shows the key once: choose **Copy key**, keep - it somewhere safe, then **I've saved this key**. Core keeps only a digest. The - dialog's **How to call** card shows the API base URL and sample requests. -5. Give the application developer the key, the API base URL and the model ID to use - with the default model provider (Sessions must name `agent.model`). They follow the - [API quickstart](quickstart.md). - -**Overview** tracks the setup in a **Getting started** checklist, in any order: -**Get sandboxes ready** ([add a node](nodes.md)), **Set a default model**, -**Create a project and issue a key**, and **Run the first Session**. After you hide it, -**Show Getting started** in the sidebar brings it back. - -An existing pre-rename installation at `~/.parsar/core` blocks a new default install. -Historical conversion is not supported. Preserve the existing installation and explicitly -choose another `--install-dir`. See [installation version policy](operations.md#installation-version-policy). - -## What the installer creates +### What the installer creates The installation directory, `~/.oac/core` by default, mode `0700`: @@ -479,30 +427,27 @@ The installation directory, `~/.oac/core` by default, mode `0700`: | `secrets/core.key` | The Core key | | `secrets/credential.key` | Encryption key for credentials stored in the database. Back it up with the database; never replace it | | `secrets/database.password` | PostgreSQL password | -| `state.json` | Format 2, installation ID, Compose project name, image IDs and source commit. Written by the tools only | -| `generated/` | Files derived from `config.json`: `compose.json`, `core.env`, `core-key-digests.json`, `settings.json`, `config.schema.json`, and `runtime-history.json` or the native Core unit when used. `oac apply` rewrites them; don't edit them | -| `node-payload/` | The managed node installer, the manifest and the node files that Web serves at `/node-install/` | +| `state.json` | Installation ID, Compose project name, image IDs and source commit. Written by the tools only | +| `generated/` | Files derived from `config.json`. `oac apply` rewrites them; don't edit them | +| `node-payload/` | The node installer and files that Web serves at `/node-install/` | | `state/e2b/` | Private E2B receipts | | `native/` | Core binaries, with `--native-core` only | -Web-only installations have only `secrets/core.key` among the secrets, and no -`state/e2b/`; Core-only installations have no `node-payload/`. - -In Docker, the installer creates a Compose project named `oac-<10 hex digits>` -(`project` in `state.json`) with the containers `database`, `migrate` (runs the -migrations, then exits), `core` and `web`, and the volume `_database` that -holds all data. Core and Web publish their configured listeners. The database -publishes no port unless Core is native, when it remains on loopback. +Web-only installations have only `secrets/core.key` among the secrets. Core-only +installations have no `node-payload/`. -The database holds the sandbox backend selection, and later your Projects, keys, -nodes, default models and all execution history. Apart from Docker's own storage, -nothing is written outside your home directory: no system service and no file under -`/etc`. Native Core adds a systemd user unit, enabled from `generated/`. +In Docker, the Compose project is named `oac-<10 hex digits>` (`project` in +`state.json`), with the containers `database`, `migrate`, `core` and `web` and the +volume `_database` that holds all data. Apart from Docker's storage, +nothing is written outside your home directory. Native Core adds a systemd user +unit. -## Rerun the installer +### Rerun the installer Rerunning `./install.sh` from the same bundle repairs an installation: it reloads -missing images, restores a missing `oac` command, copies node files newly placed in -`artifacts/`, applies `config.json` and starts the services. It accepts only -`--install-dir`. It refuses a bundle from another release; see -[installation version policy](operations.md#installation-version-policy). +missing images, restores the `oac` command, applies `config.json` and starts the +services. It accepts only `--install-dir` and refuses a bundle from another +release; see [installation version policy](operations.md#installation-version-policy). + +An installation from before the rename, at `~/.parsar/core`, blocks a new default +install. Keep it and choose another `--install-dir`. diff --git a/docs/getting-started/nodes.md b/docs/getting-started/nodes.md index 8ed60ef88..bea43a03b 100644 --- a/docs/getting-started/nodes.md +++ b/docs/getting-started/nodes.md @@ -20,7 +20,7 @@ node protocol, manual registration, placement and failure handling. With the default online installation, nodes follow HTTPS redirects to download their matching Runtime and provider files directly from the release, verifying sizes and SHA-256 checksums before use. Core and Web do not download these files. - For nodes without release access, use the [offline bundle](install.md#download-a-release) + For nodes without release access, use the [offline bundle](install.md#installer-options) on the Web host so it serves the files locally. Verified local files are reused. - **A sandbox backend is chosen.** The installer selects microsandbox unless you chose otherwise. After `--sandbox none`, the **Nodes** page first asks you to choose @@ -238,12 +238,10 @@ WebSocket doesn't pass the reverse proxy. ## Change the sandbox backend or size -Changing backend type requires an explicit reset. Same-provider Docker and -microsandbox size or Runtime edits advance the target generation without retiring -nodes or moving existing Sessions. Version 2 nodes prepare the target independently; -existing allocations and suspended VMs keep their original generation. A qualified -older serving generation can still accept new Sessions when it has capacity, -including while a newer target is preparing or has failed. +Change the backend or sandbox size in Web under **System** → **Sandbox backend**. +What each change does, and when it needs a reset, is in +[Sandbox deployment](../configuration.md#sandbox-deployment). This section covers +only what happens on the nodes. Node program version updates are not supported. `--update` refuses without changing node state. Preserve an older installation and its Runtime data; provision a fresh diff --git a/docs/getting-started/operations.md b/docs/getting-started/operations.md index 3c4630731..2ad9a1273 100644 --- a/docs/getting-started/operations.md +++ b/docs/getting-started/operations.md @@ -119,15 +119,17 @@ 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](../../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. - -To rotate an application key, issue another key in the same Project, update the -application, then **Revoke** the old key. **Archive** disables all of a Project's keys -and keeps its assets and accepted work. Administrators can inspect and delete retained -resources but can't execute with the Core key. +Create Projects and issue keys in Web, on **Projects and keys**, or through the +[Core API](../../contracts/agents-api/admin-api.md) under `/core/v1/projects`. How +Projects and keys behave is in [Projects own assets](../design-principles.md#projects-own-assets). + +To rotate an application key: + +1. Issue a new key in the same Project. +2. Update the application to use it. +3. **Revoke** the old key. + +**Archive** disables every key of a Project and keeps its assets. ## Data and current-release repair diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index 34f90b068..5eec07a9d 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -1,33 +1,39 @@ # Run your first Session -Before starting, [install Core and Web](install.md), issue a Project API key, and -prepare a ready managed node or E2B backend. You also need Python 3.9+ and model -provider access. This walkthrough uses Codex with a Responses-compatible provider. +This walkthrough takes you from a Project API key to an agent that has created a file +and reported back. You need: -Core serves the OpenAI Agents API. Applications use the official OpenAI SDK with two -environment variables, which the SDK reads by default: +- a Project API key and the API base URL, from your administrator + ([Sign in to Web](install.md#sign-in-to-web)); +- a ready node or E2B backend, so Core has somewhere to run the agent + ([Nodes](nodes.md)); +- Python 3.9 or newer; +- a model: either the installation's default model, set by your administrator, or + your own provider's model ID, base URL and API key. -| Variable | Value | From | -| --- | --- | --- | -| `OPENAI_BASE_URL` | The installation's API base URL: its public URL followed by `/v1`, such as `https://core.example/v1` | The administrator; Web's **System** page shows it as **API base URL** | -| `OPENAI_API_KEY` | A Project API key | The administrator issues it on **Projects and keys**; see [Sign in to Web](install.md#sign-in-to-web) | +The example uses Codex. Other harnesses are covered in the +[user guide](../user-guide.md#choose-a-harness-and-a-model). -The Project API key authenticates your application to this Core. It is separate from -the model provider's key that a harness uses, and neither belongs in source control. -The API base URL reaches Core directly; Web does not serve `/v1`. +## 1. Connect -## First request +Core serves the OpenAI Agents API, so the official OpenAI SDK works unchanged. It +reads two environment variables: -Use the pinned client version: +| Variable | Value | +| --- | --- | +| `OPENAI_BASE_URL` | The API base URL: the public URL plus `/v1`, such as `https://core.example/v1`. Web's **System** page shows it | +| `OPENAI_API_KEY` | Your Project API key | ```sh python3 -m venv .venv . .venv/bin/activate pip install openai==3.13.0 export OPENAI_BASE_URL=https://core.example/v1 -read -rs OPENAI_API_KEY && export OPENAI_API_KEY # paste the Project API key; it isn't echoed +read -rs OPENAI_API_KEY && export OPENAI_API_KEY # paste the key; it is not echoed ``` +Check access. This runs no model and creates no sandbox: + ```python from openai import OpenAI @@ -35,23 +41,20 @@ client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEY print(client.beta.agents.list().data) ``` -`read -rs` keeps the key out of your shell history. This read checks access; it runs no -model and creates no sandbox. The same request with curl, which keeps the key off its -command line: +An empty list means you are connected. The same check with curl: ```sh curl "$OPENAI_BASE_URL/agents" -H "OpenAI-Beta: agents=v1" \ -H @<(printf 'Authorization: Bearer %s\n' "$OPENAI_API_KEY") ``` -All keys of a Project share its assets and execution principal; other Projects are -isolated. When the administrator rotates your key, they issue a new one in the same -Project and revoke the old one; your assets stay. +## 2. Start a Session -## Run a Session +A Session is one agent conversation with its own workspace. With +`openai_hosted`, Core creates a sandbox for it on a node or E2B and starts the harness +inside. -Set the provider's exact model ID and Responses API base URL. Use a test account -that is authorized to make a model request: +With the installation's default model, skip this. To use your own provider: ```sh export MODEL_NAME='your-model-id' @@ -59,89 +62,37 @@ export MODEL_BASE_URL='https://your-provider.example/v1' read -rs MODEL_API_KEY && export MODEL_API_KEY ``` - -A Core-hosted Session (`openai_hosted`) runs in a sandbox that Core creates: on a node -with free capacity, or on E2B. Core prepares the daemon, native harness and workspace -inside it. The installation needs a ready node or an E2B backend; see -[Nodes](nodes.md). - ```python import os +extra = {"agent": {"x_agents_core": {"harness": "codex"}}} +if os.environ.get("MODEL_API_KEY"): + extra["agent"]["model"] = os.environ["MODEL_NAME"] + extra["x_agents_core"] = {"model_provider": { + "protocol": "responses", + "base_url": os.environ["MODEL_BASE_URL"], + "api_key": os.environ["MODEL_API_KEY"], + }} + session = client.beta.agents.sessions.create( environment={"type": "openai_hosted"}, input="Create /workspace/hello.txt with a short greeting, then describe it.", - extra_body={ - "agent": { - "model": os.environ["MODEL_NAME"], - "x_agents_core": {"harness": "codex"}, - }, - "x_agents_core": { - "model_provider": { - "protocol": "responses", - "base_url": os.environ["MODEL_BASE_URL"], - "api_key": os.environ["MODEL_API_KEY"], - } - }, - }, + extra_body=extra, ) print(session.id) ``` -This makes a real model request and may incur charges. If the administrator set a -default model for the harness, omit `x_agents_core.model_provider`; `agent.model` is -still required, so ask the administrator which model ID the default provider serves. -SDK 3.13.0 replaces an ordinary body field with the matching `extra_body` field -instead of merging nested fields, so keep the whole `agent` object in `extra_body`. - -## Core extensions: x_agents_core - -`/v1` has exactly the official routes. Core's additions are fields inside -`x_agents_core`, passed through `extra_body`; any other member is rejected with 400. - -| Field | Where | Meaning | -| --- | --- | --- | -| `x_agents_core.harness` | A saved Agent, or the Session's inline `agent` | Which native harness runs the Agent: `codex` (Codex), `claude_sdk` (Claude Code) or `mcode` (MiniMax Code). Omitted: the installation's default harness (`core.default_harness`, Codex unless changed) | -| `x_agents_core.model_provider` | A saved Agent, or Session creation | The model provider bundle: `protocol`, HTTPS `base_url`, write-only `api_key`, and for `mcode` also `context_window` and `max_output_tokens`. Reads return `api_key_configured` instead of the key | - -The provider's protocol must match the harness: +This makes a real model request and may incur charges. -| Harness | `protocol` | Also required | -| --- | --- | --- | -| Codex (`codex`) | `responses` | The provider's exact model ID in `agent.model` | -| Claude Code (`claude_sdk`) | `anthropic` | The provider's exact model ID | -| MiniMax Code (`mcode`) | `anthropic` | `context_window` and `max_output_tokens` | +- `x_agents_core` holds Core's additions to the OpenAI API; see + [Core extensions](../api/public-agent-api.md#core-extensions-x_agents_core). +- Keep the whole `agent` object in `extra_body`. SDK 3.13.0 replaces a body field with + the matching `extra_body` field instead of merging them. -See [harness selection](../../contracts/agents-api/harness-selection.md) and -[model execution](../../contracts/agents-api/model-execution.md) for the full contract. -Selecting a harness doesn't make an unsupported model or operation work. +## 3. Wait for the result -## Model providers - -A Session takes its model provider from the first of these that has one; bundles are -never merged: - -1. `x_agents_core.model_provider` in the Session creation request; -2. the saved Agent's `x_agents_core.model_provider`; -3. the installation's default model for the harness, set in Web on **System**, - **Default model**. - -| Environment | Request or saved Agent | Default model | None of them | -| --- | --- | --- | --- | -| `openai_hosted` | Used | Used | 400 `model_provider_required` | -| `self_hosted` | Used | Never | 400 `model_provider_required` | -| `none` | Rejected with 400 `unsupported_or_invalid_configuration` | Used | Allowed: the device's own environment supplies the model | - -A Session freezes its provider when it is created; later changes to the Agent or the -default affect only new Sessions. Core encrypts the key with the Session and never -returns it. Self-hosted Sessions always bring their own provider, because the default -holds the operator's key and the executor host belongs to the application; see -[Self-hosted executors](self-hosted.md). - -## Wait for the result - -Continue in the same Python process. A Session ID confirms creation, not success. -This bounded loop reads durable state instead of resubmitting work: +A Session ID confirms creation, not success. Poll durable state; never resubmit to +"retry": ```python import time @@ -152,23 +103,22 @@ for _ in range(120): turn = turns[0] print("Turn:", turn.id, turn.status) print(client.beta.agents.sessions.items.list(session.id).data) - if turn.status != "completed": - raise RuntimeError("Inspect the recorded Turn and Items before retrying") break - current = client.beta.agents.sessions.retrieve(session.id) - if current.status == "failed": + if client.beta.agents.sessions.retrieve(session.id).status == "failed": raise RuntimeError("Session preparation failed; inspect its Environment") time.sleep(1) else: - raise TimeoutError(f"Session {session.id} is still pending; inspect it before retrying") + raise TimeoutError(f"Session {session.id} is still running; inspect it before retrying") ``` -Success means the Turn is `completed` and its recorded output describes the created -file. A timeout does not cancel the task or prove failure. The -[user guide](../user-guide.md) explains how to inspect files, send another message, -add Skills/Plugins/MCP, cancel work and recover after disconnection. +Success is a `completed` Turn whose Items describe the new file. A timeout neither +cancels the work nor proves it failed. + +## Next steps -Files, Artifacts, cancellation and their current limits are in the -[coverage ledger](../../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](../api/README.md) lists every route. +| To | Read | +| --- | --- | +| Stream output, send follow-up messages, upload files, add Skills or MCP, cancel | [User guide](../user-guide.md) | +| See every resource with request and response examples | [Agents API guide](../api/public-agent-api.md) | +| Run the agent on your own machine | [Self-hosted execution](self-hosted.md) | +| See a complete application | [Examples](../examples.md) | diff --git a/docs/getting-started/self-hosted.md b/docs/getting-started/self-hosted.md index 324d774fc..e1d492834 100644 --- a/docs/getting-started/self-hosted.md +++ b/docs/getting-started/self-hosted.md @@ -6,17 +6,15 @@ creates the Session through `/v1` and receives a command that installs and conne Linux, macOS and Windows use the same Runtime protocol. Core-managed Providers remain Linux-only. -The daemon runs with its launching user's permissions and adds no inner -filesystem, permission or network sandbox. Its tools may access that user's files -and Runtime credentials. Managed isolation belongs to the outer Environment; -self-hosted operators choose any outer isolation they need. See the -[native installation guide](../self-hosted-native.md) for prerequisites, commands -and supported platforms. - -An executor credential works for one Environment only. It cannot call the Agent -API, Core API or node enrollment. Default model providers never apply to -self-hosted Sessions: the request or Agent must carry its own model provider. -Otherwise creation fails with 400 `model_provider_required`. +**The daemon is not a sandbox:** tools run with its launching user's permissions. +Use a container or VM if you need isolation; see +[Runtime and outer isolation](../design-principles.md#runtime-and-outer-isolation). +Platforms, prerequisites and commands are in the +[native Runtime guide](../self-hosted-native.md). + +An executor credential works for one Environment only, and for nothing else. The +Session must bring its own model provider; the installation default never applies +([why](../user-guide.md#which-model-provider-a-session-uses)). ## Connect a host @@ -50,6 +48,8 @@ Otherwise creation fails with 400 `model_provider_required`. installation directory when prompted. Installation creates the workspace if needed, starts the daemon and checks its connection. For automation, append `--non-interactive --harness codex` and optionally `--install-dir ABS`. +3. Send a Turn. A connected Environment proves only the machine connection; the + first Turn checks the harness and model. In Web, open the **Self-hosted** Session and copy the command under **Connect a host**. A command expires after 30 minutes; fetch the Session again for a fresh @@ -57,10 +57,6 @@ one. The [native guide](../self-hosted-native.md#install-and-connect) covers ret platform prerequisites and credential storage. Core must be reachable from the host with TLS outside loopback. Native installation does not require Docker. -A connected Environment proves only the machine connection. Send a Turn to check -the selected harness and model. Core supplies the Session's model provider over -this Environment's authenticated executor connection. The host's user and tools -running with that user's permissions can access locally stored Runtime data. ## Local capability directories diff --git a/docs/self-hosted-native.md b/docs/self-hosted-native.md index 56b099022..4d7d183da 100644 --- a/docs/self-hosted-native.md +++ b/docs/self-hosted-native.md @@ -5,13 +5,10 @@ Physical machines, VMs and user-owned sandboxes use the same installer. Core doe not create or reclaim these machines. Core-managed Docker, E2B and microsandbox Providers remain Linux-only and receive prebuilt Runtime images or templates. -The daemon runs with its starting account's permissions, without an inner sandbox -or privilege elevation. Tools can access whatever that account can access. Use an -outer container or VM when isolation is required. Connection authentication, -Project/Environment authorization, credential permissions, Files path validation, -process cleanup and snapshot consistency still apply; they do not isolate tools -from their own account. `disabled` and `restricted` network modes require an outer -implementation that enforces them. +**The daemon is not a sandbox.** Tools can access whatever its account can. Use an +outer container or VM when you need isolation; see +[Runtime and outer isolation](design-principles.md#runtime-and-outer-isolation). +`disabled` and `restricted` network modes need an outer layer that enforces them. ## Platforms and prerequisites @@ -128,11 +125,9 @@ Harness while the daemon is running, restart it to refresh Harness discovery. `status` reports local profile/PID-file information only. Check **Host connection** in Core or the Environment connection API for authenticated connection state. -A connected Environment proves machine authentication, not model availability. -Configure the model provider through the existing Session/Agent mechanism and -send a Turn to verify execution. Rotate a credential by stopping the daemon, -replacing the JSON at the configured path with the rotated credential for the -same `key_id`, and starting again. Revocation blocks the old credential. +A connected Environment proves machine authentication, not model availability: +send a Turn to verify execution. To rotate or revoke the credential, see +[Rotate or revoke](getting-started/self-hosted.md#rotate-or-revoke). An incompatible daemon version, component version or modified installation is an explicit error. Use a separate installation directory; there is no old-version diff --git a/docs/user-guide.md b/docs/user-guide.md index 72320a4b0..a2ba72954 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -1,115 +1,156 @@ -# Use OpenAgentCore +# User guide -Complete the [first Session walkthrough](getting-started/quickstart.md) before using -this guide. It provides `client` and `session`; the examples below continue that -Session. For exact request fields, use the [API reference](api/README.md). +Common tasks for application developers. Start with the +[quickstart](getting-started/quickstart.md); it sets up `client` and `session`. Every +operation here is shown with SDK and HTTP examples in the +[Agents API guide](api/public-agent-api.md). ## Choose where a task runs -| Environment | What you prepare | Next step | +A Session's `environment.type` decides where its agent works: + +| Environment | Runs on | You prepare | | --- | --- | --- | -| `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](getting-started/self-hosted.md) to the returned Environment | -| `none` | An existing device connection and its configured Harness | Check the qualified profile in [Harness selection](../contracts/agents-api/harness-selection.md) | +| `openai_hosted` | A sandbox Core creates on a node or E2B | Nothing; the administrator provides capacity | +| `self_hosted` | Your own Linux, macOS or Windows machine | The machine, a workspace directory and the daemon. See [self-hosted execution](getting-started/self-hosted.md) | +| `none` | An existing device connection, no workspace | A connected device with its harness | + +Placement, expiry and supported combinations: +[Environment contract](../contracts/agents-api/environments.md). + +## Choose a harness and a model + +The harness is the agent program that runs your Session. Set it in +`x_agents_core.harness` on the Agent; if you don't, the installation's default +(Codex unless changed) is used. + +| Harness | `harness` | Native model parameters (`harness_config`) | +| --- | --- | --- | +| Codex | `codex` | `model_reasoning_effort` | +| Claude Code | `claude_sdk` | `effort`, `thinking` | +| MiniMax Code | `mcode` | None. The provider must set `context_window` and `max_output_tokens` | + +- **Model.** `agent.model` is the provider's exact model ID. An inline Agent on an + `openai_hosted` or `none` Session may omit it to use the installation default's + model. Saved Agents always need one. +- **Provider protocol.** Any harness accepts `responses`, `anthropic` or + `chat_completions`; the Runtime converts when the harness doesn't speak it + natively. Native model parameters need a native protocol. +- **Native parameters.** `x_agents_core.harness_config` passes the harness's own + settings; see [native model configuration](../contracts/agents-api/harness-onboarding.md#native-model-configuration). -Use the [Environment contract](../contracts/agents-api/environments.md) for placement, -expiry and supported combinations. Model selection and provider precedence are -explained once in the [application quickstart](getting-started/quickstart.md#model-providers). +Selecting a harness doesn't make an unsupported model or operation work; see +[harness selection](../contracts/agents-api/harness-selection.md). -## Continue a Session +### Which model provider a Session uses -A Session keeps the conversation and its fixed execution configuration. Submit a -follow-up after the previous Turn settles: +A Session takes its model provider from the first of these that has one. They are +never merged: + +1. `x_agents_core.model_provider` in the Session creation request; +2. the saved Agent's `x_agents_core.model_provider`; +3. the installation's default model configuration for the harness, set by the + administrator. It also supplies the model and native parameters when the Session + leaves them out. + +| Environment | Request or Agent provider | Installation default | Neither | +| --- | --- | --- | --- | +| `openai_hosted` | Used | Used | 400 `model_provider_required` | +| `self_hosted` | Used | Never | 400 `model_provider_required` | +| `none` | Rejected (400) | Used | Allowed: the device supplies the model | + +Self-hosted Sessions never use the default, because it holds the operator's key and +your machine is outside the operator's control. A Session freezes its provider at +creation; later changes affect only new Sessions. Full rules: +[model execution](../contracts/agents-api/model-execution.md). + +## Follow up and steer + +Send another message to the same Session to continue with its history and workspace: ```python -client.beta.agents.sessions.events.create( - session.id, - events=[{ - "type": "agent.session.input.message", - "input": [{ - "role": "user", - "content": [{"type": "input_text", "text": "Summarize the file you created."}], - }], - }], -) +client.beta.agents.sessions.events.create(session.id, events=[{ + "type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Summarize the file you created."}]}], +}]) ``` -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](../contracts/agents-api/message-input.md) -for supported content, steering and idempotency rules. +- **Idle Session:** the message starts a new Turn. +- **Running Turn:** the message joins it (steering). It never starts a parallel task. +- **Different configuration or workspace:** create a new Session. + +See [Send input](api/public-agent-api.md#send-input). -## Prepare Skills, Plugins and MCP +## Watch the output live -Select capabilities when creating the Session, before sending work that needs them. -Runtime installs one snapshot and passes its Skill paths and MCP declarations to the -Harness. Reconnect reuses that snapshot; changing local source files does not alter -an existing Session. +Open the event stream before sending input, and print text as it arrives: -| Task | Guide | +```python +with client.beta.agents.sessions.events.stream(session.id) as stream: + for event in stream: + if event.type == "agent.session.turn.output_text.delta": + print(event.delta, end="", flush=True) + if event.type in {"agent.session.turn.completed", "agent.session.turn.failed", "agent.session.turn.cancelled"}: + break +``` + +The stream is live only. After a disconnect, read Turns and Items to fill the gap. +See [Stream events](api/public-agent-api.md#stream-events). + +## Give the agent Skills, Plugins and MCP + +Choose capabilities when you create the Session. The Runtime installs them once, as a +snapshot; editing the source later doesn't change a running Session. + +| To | Use | | --- | --- | -| Upload a Skill source and select a version | [Source Files and Skills](../contracts/agents-api/source-files.md) | -| Use local Skill/Plugin directories | [Local capability directories](getting-started/self-hosted.md#local-capability-directories) | -| Provide initial files, user-directory packages or setup | [Environment Templates](../contracts/agents-api/environment-templates.md) | -| Declare tools, MCP and function callbacks | [Execution tools](../contracts/agents-api/execution-tools.md) | -| Choose a supported tool policy | [Tool policy](../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.md) for dependencies and -platform support. Missing preparation fails before execution; do not retry a task -as a new Session to work around an unresolved preparation error. - -## Read results and files - -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](../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](../contracts/agents-api/environment-files.md) | -| Artifacts | Retrieve captured outputs associated with execution | [Artifacts and public resources](api/public-agent-api.md) | -| Source Files | Upload input used by a Skill or other declared resource | [Source Files](../contracts/agents-api/source-files.md) | +| Upload a Skill and pick a version | [Skills](api/public-agent-api.md#skills) | +| Reuse packages, files, setup and network rules | [Environment Templates](api/public-agent-api.md#environment-templates) | +| Call your own code from the agent | [Function tools](api/public-agent-api.md#function-tools) | +| Connect an MCP server, with credentials | [Execution tools](../contracts/agents-api/execution-tools.md) and [Vaults](api/public-agent-api.md#vaults) | +| Use Skill or Plugin directories on your machine | [Local capability directories](getting-started/self-hosted.md#local-capability-directories) | + +System packages must already be in the machine or image. Preparation errors fail the +Session before any work runs; fix the cause instead of retrying in a new Session. -These resources have different lifetimes. Deleting a Session does not erase files -from a user-owned machine. Reclaiming managed compute is a separate Environment -operation; stopping an executor does not imply reclamation. +## Send files and get results + +| To | Use | +| --- | --- | +| Put a file in the workspace | [Workspace files](api/public-agent-api.md#workspace-files) | +| Upload once, reference by ID | [Source Files](api/public-agent-api.md#source-files) | +| Download what the agent wrote to `outputs/` | [Artifacts](api/public-agent-api.md#artifacts) | +| Read the conversation and tool results | [Turns and Items](api/public-agent-api.md#turns-and-items) | + +Deleting a Session doesn't erase files on your own machine. Reclaiming a managed +sandbox is a separate operation. ## Cancel and recover -To cancel current work: +Cancel the current Turn: ```python -client.beta.agents.sessions.events.create( - session.id, - events=[{"type": "agent.session.input.cancel"}], -) +client.beta.agents.sessions.events.create(session.id, events=[{"type": "agent.session.input.cancel"}]) ``` -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](../contracts/agents-api/core-errors.md). +The work has stopped when the Turn reads `cancelled`, not when the request returns. -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 -execution, restart the same installation with its retained workspace and native -history; follow the [operator lifecycle](self-hosted-native.md#add-harnesses-and-operate-the-installation). -A new Session captures a new configuration, not the history of a deleted one. +After a lost response or connection: + +1. Read the Session, its Turns and Items. +2. If the work isn't there, retry with the **same** `Idempotency-Key`. +3. Never resend without a key; you may run the work twice. + +On a self-hosted machine, restart the same installation to keep its workspace and +history; see [operating the installation](self-hosted-native.md#add-harnesses-and-operate-the-installation). ## Diagnose a failure -1. Check the Session, latest Turn and required actions in the API or Web. -2. Confirm that the Environment is connected and its selected Harness is available. -3. Check the model/provider and capability combination against - [supported execution](../contracts/agents-api/execution-tools.md). -4. Follow [operations and troubleshooting](getting-started/operations.md) for service - logs, credentials and node readiness. Runtime observations may be stale; the - [diagnostics contract](../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](api/README.md) at hand when diagnosing authentication errors. +1. Read the Session's `status` and `error`, and the latest Turn's `error`. +2. Check that the Environment is connected and its harness is available. +3. Check the harness, model and tool combination in + [execution tools](../contracts/agents-api/execution-tools.md). +4. Ask the administrator to check [operations and troubleshooting](getting-started/operations.md#troubleshooting) + for service logs, credentials and node readiness. + +A 401 usually means a key from the wrong namespace; see the [API index](api/README.md). diff --git a/docs/web/README.md b/docs/web/README.md index f46787472..e4a3d2c44 100644 --- a/docs/web/README.md +++ b/docs/web/README.md @@ -37,15 +37,8 @@ deployment sandbox nodes. Deployment sandbox management selects E2B, Docker or microsandbox; caller-managed `self_hosted` Runtimes remain a separate application path. -A Project owns one tenant and one principal. All its keys share assets and -permissions; writes record the individual key as provenance. Projects and keys -live only in PostgreSQL. Key issuance returns plaintext once and stores its digest. -Rotate by issuing another key and revoking the old one. Archive disables every key -in the Project while retaining assets and admitted work. - -The management API cannot create or edit arbitrary application resources, start -Sessions, submit input or cancel execution. Applications perform those operations -through `/v1`. Core has no API users, roles or memberships. +How Projects and keys behave, and what administrators can and cannot do, is in +the [design principles](../design-principles.md#projects-own-assets). ## Connect and develop diff --git a/docs/web/architecture.md b/docs/web/architecture.md index 9cad3ec53..527bff5bb 100644 --- a/docs/web/architecture.md +++ b/docs/web/architecture.md @@ -53,18 +53,9 @@ grant a browser execution authority. | Core API and PostgreSQL | Project isolation, resource state, deletion preconditions, audit and scheduling | | Runtime and native adapters | Existing allocation, process lifecycle and execution protocols | -A Project owns one tenant and one principal; its keys have equal access to its -assets. Projects and keys are database records. Configuration contains deployment -settings, not business identities. Core has no separate API-user or role model. - -Revoking one key prevents new authentication without removing assets or admitted -work. Archiving a Project disables all its keys and retains resources for -administrator inspection and deletion. - -Management adds no execution path. It can inspect metadata and history and apply -existing deletion rules. It cannot edit arbitrary resources, create Sessions, send -input or cancel work. A deletion conflict cannot be resolved by an implicit -cancellation from the console. +Projects, keys and administrator authority follow the +[design principles](../design-principles.md#projects-own-assets). The console adds +no execution path: a deletion conflict is never resolved by an implicit cancellation. Secret fields remain write-only; Skill source and Artifact content have explicit read routes, while Source File content does not have an administrator download diff --git a/docs/web/core-connection.md b/docs/web/core-connection.md index cf654432e..dc618f530 100644 --- a/docs/web/core-connection.md +++ b/docs/web/core-connection.md @@ -64,18 +64,9 @@ and display only. Keep deployment, application, node and provider credentials ou ## Projects and application keys -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](../../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 -PostgreSQL, independently of deployment configuration. - -Issuance returns plaintext once; Core stores its digest. Deliver the new key to the -application privately. Rotate by issuing a replacement in the same Project and -revoking the old key. Archive disables every key while retaining assets and admitted -work. Ordinary metadata reads cannot recover plaintext. +Installation creates no Project or key. Create them on **Projects and keys** or +through the [administrator API](../../contracts/agents-api/admin-api.md); see +[Projects and API keys](../getting-started/operations.md#projects-and-api-keys). ## Verification and diagnosis From 35934699ca0c269876bce3fba4b56ab234ffbdb5 Mon Sep 17 00:00:00 2001 From: saladday <1203511142@qq.com> Date: Tue, 29 Sep 2026 18:35:31 +0800 Subject: [PATCH 2/2] docs: add a usage-level Agents API guide and an examples chapter - docs/api/public-agent-api.md becomes the Agents API guide: every public resource with official OpenAI SDK and plain HTTP examples, plus pagination, idempotency, errors, x_agents_core, streaming events, function tools, the three kinds of file, Skills, templates, Vaults and the differences from OpenAI. SDK calls were checked against SDK 3.13.0 for method, path and headers. - API index: runnable Core API commands for common administrator tasks. - docs/examples.md: the cases chapter, mapping each feature of the Parsar example to its API and guide section; example READMEs link to it. - Register the examples page and retitle the API guide on the docs site, and regenerate the site. --- .../content/docs/bootstrap-projects-keys.mdx | 15 +- apps/docs/content/docs/concepts.mdx | 166 +++-- apps/docs/content/docs/configure.mdx | 26 +- apps/docs/content/docs/console.mdx | 11 +- apps/docs/content/docs/examples.mdx | 65 ++ apps/docs/content/docs/execution-model.mdx | 15 +- apps/docs/content/docs/hosted-providers.mdx | 12 +- apps/docs/content/docs/index.mdx | 63 +- apps/docs/content/docs/install.mdx | 611 ++++++++--------- apps/docs/content/docs/meta.json | 1 + apps/docs/content/docs/public-api.mdx | 91 ++- apps/docs/content/docs/quickstart.mdx | 166 ++--- .../content/docs/self-hosted-execution.mdx | 26 +- apps/docs/content/docs/self-hosted-native.mdx | 19 +- apps/docs/content/docs/sessions.mdx | 636 +++++++++++++++--- apps/docs/content/docs/troubleshooting.mdx | 20 +- apps/docs/content/docs/user-guide.mdx | 213 +++--- apps/docs/content/guide-sources.json | 64 +- apps/docs/scripts/guides.json | 12 +- docs/api/README.md | 91 ++- docs/api/public-agent-api.md | 634 ++++++++++++++--- docs/examples.md | 60 ++ example/README.md | 8 +- example/parsar/README.md | 17 +- scripts/name-allowlist.json | 10 + 25 files changed, 2044 insertions(+), 1008 deletions(-) create mode 100644 apps/docs/content/docs/examples.mdx create mode 100644 docs/examples.md diff --git a/apps/docs/content/docs/bootstrap-projects-keys.mdx b/apps/docs/content/docs/bootstrap-projects-keys.mdx index 85b78629f..7b20dd5de 100644 --- a/apps/docs/content/docs/bootstrap-projects-keys.mdx +++ b/apps/docs/content/docs/bootstrap-projects-keys.mdx @@ -67,18 +67,9 @@ and display only. Keep deployment, application, node and provider credentials ou ## Projects and application keys -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/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 -PostgreSQL, independently of deployment configuration. - -Issuance returns plaintext once; Core stores its digest. Deliver the new key to the -application privately. Rotate by issuing a replacement in the same Project and -revoking the old key. Archive disables every key while retaining assets and admitted -work. Ordinary metadata reads cannot recover plaintext. +Installation creates no Project or key. Create them on **Projects and keys** or +through the [administrator API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md); see +[Projects and API keys](/troubleshooting#projects-and-api-keys). ## Verification and diagnosis diff --git a/apps/docs/content/docs/concepts.mdx b/apps/docs/content/docs/concepts.mdx index 729007af8..762bedd3e 100644 --- a/apps/docs/content/docs/concepts.mdx +++ b/apps/docs/content/docs/concepts.mdx @@ -3,103 +3,95 @@ title: "Concepts and ownership" description: "Projects, credentials and the boundary between applications, administration and execution." --- -OpenAgentCore is an open-source implementation of the OpenAI Agents API. Its public -contract follows the repository's pinned upstream baseline; documented native -harness differences remain explicit. Core extensions must not silently change -upstream resource shapes or execution semantics. +OpenAgentCore implements the OpenAI Agents API. Its public contract follows the +repository's pinned upstream baseline. Documented native harness differences stay +explicit; Core extensions never silently change upstream resource shapes or +execution semantics. ## Three namespaces, three credentials -Applications use `/v1` with a Project API key. Administrators use `/core/v1` -with the Core key. Nodes and Runtime daemons use `/api/v1` with their own scoped -machine credentials. The [API index](/public-api) owns the complete caller, -credential and route matrix. +Applications, administrators and machines each use their own namespace and +credential. The [API index](/public-api) owns the complete matrix. -Web calls the management API through its server and keeps the Core key there. -Signing in grants administrator access to that deployment; it does not create -an application Session or give the browser a Project API key. - -This is a separation of API authority, not a claim that a deployment administrator -cannot possess application credentials. An administrator can issue an API key and -use it separately. The console itself has no impersonation or execution operation. -API-key plaintext is returned once on issuance, never on reads. +Separating API authority does not stop an administrator from holding application +credentials: they can issue a Project API key and use it like any application. ## Projects own assets -A Project owns one execution tenant and its assets. Multiple named API keys belong -to the Project and share its principal, permissions and resources. Each write keeps -its actual key identity for provenance. There are no Core users, roles, memberships -or read-only keys. Names are labels; stable IDs identify Projects and keys. - -Projects and application API keys live only in PostgreSQL. The console and -management API use the same records. Configuration contains deployment settings, -not application credentials or Project definitions. Issue a new key in the same -Project and revoke the previous one to rotate credentials. Revocation affects only -that key and preserves assets, provenance and accepted execution. Explicit Project -archive revokes every key and blocks new issuance in that Project. -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/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. - -## Resource isolation and administrator authority - -Agent API reads, writes and references are scoped to the authenticated key's Project. -A foreign resource remains indistinguishable from an absent resource under the -existing public operation's rules. Deployment nodes, configured model endpoints -and startup settings are deployment infrastructure, not shared business assets. - -Administrators can inspect resources and execution history, delete resources under -the same rules as their public deletion operations, manage Projects and API keys, -issue node enrollment tokens and self-hosted executor credentials, and query -operational counts and usage. They cannot use management endpoints to -create, copy or edit arbitrary assets, start a Session, send an event, cancel -work, or read stored credentials. Project keys share all assets within their -Project; nothing is shared or copied across Projects. +A Project owns one execution tenant and its assets. + +- **Keys.** A Project has one or more named API keys. They share its principal, + permissions and resources. Each write records the key that made it. +- **No users or roles.** Core has no users, roles, memberships or read-only keys. + Names are labels; stable IDs identify Projects and keys. +- **Storage.** Projects and keys live only in PostgreSQL, never in deployment + configuration. A key's plaintext is returned once, at issuance. +- **Rotation.** Issue a new key in the same Project, then revoke the old one. + Revoking a key keeps assets, provenance and accepted work. +- **Archive.** Archiving a Project revokes every key and blocks new ones. + Administrators can still inspect and delete its resources. + +The Core key is a deployment credential, managed separately; see +[Core key](/troubleshooting#core-key). Product concepts such as users, +workspaces and business permissions stay outside Core: +a product like Parsar is an ordinary API-key holder in a Project. + +## Resource isolation + +Agents API reads, writes and references are scoped to the key's Project. A resource +in another Project is indistinguishable from an absent one. Nothing is shared or +copied across Projects. Nodes, configured model endpoints and startup settings are +deployment infrastructure, not business assets. + +## What administrators can and cannot do + +| Administrators can | Administrators cannot | +| --- | --- | +| Inspect resources and execution history | Create, copy or edit arbitrary assets | +| Delete resources, under the public deletion rules | Start a Session, send input or cancel work | +| Manage Projects and API keys | Read stored credentials | +| Issue node enrollment tokens and executor credentials | Impersonate an application | +| Query operational counts and usage | | + +Web signs in with the Core key and keeps it on its server; signing in never creates +a Session or gives the browser a Project API key. ## Runtime and outer isolation -The same daemon and Core protocol serve self-hosted Linux, macOS and Windows. -OS differences belong to Runtime implementations; harness differences belong to -adapters. Managed Providers remain Linux-only. Runtime prepares capabilities and -executes work; Providers create, bootstrap and reclaim outer Environments. - -The daemon runs tools with its launching user's permissions. It does not add a -filesystem, permission or network sandbox, including on Linux. Outer Docker/E2B/ -microsandbox Environments provide managed isolation. Credential authentication, -ordinary private storage, atomic writes, locks and process cleanup remain required, -but do not protect Runtime data from tools running as the same user. Local -capability snapshots share the managed parser and do not create a second security -boundary. See the [native Runtime guide](/self-hosted-native) for current platform -validation limits. - -## Secrets and evidence - -Credential values, model credentials and confidential template initialization are -write-only through resource APIs, including administrator reads. Public metadata -projections are reused by the management API. This does not redact arbitrary -user-authored conversation text, Skill source or Artifact content: administrators -who inspect those records see their recorded contents. - -Public writes retain their actual API-key provenance. Administrator writes retain -a separate audit identity and target Project. The console's fixed actor label is -display-only; Core trusts the Core key, not that forwarded label. Audit failure rolls -back the business transaction. Reads are not audited. Resources from the removed -copy operation keep their `admin_copy` ownership, distinct from historical unknown -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/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 +The same daemon and protocol serve self-hosted Linux, macOS and Windows. OS +differences belong to Runtime implementations; harness differences belong to +adapters. Managed Providers are Linux-only. + +**The daemon is not a sandbox.** It runs tools with its launching user's +permissions and adds no filesystem, permission or network isolation, on any OS. +Isolation comes from the outer Environment: Docker, E2B or microsandbox for managed +Sessions, or whatever container or VM you choose for a self-hosted machine. +Authentication, private storage, locks and process cleanup still apply, but they do +not protect Runtime data from tools running as the same user. + +## Secrets and audit + +- **Write-only secrets.** Credential values, model keys and confidential template + data are never returned by any read, including administrator reads. Conversation + text, Skill source and Artifact content are not secrets: administrators see them. +- **Provenance.** Public writes record their API key. Administrator writes record a + separate audit identity and the target Project. Web's actor label is display-only; + Core trusts the Core key, not the label. +- **Audit is transactional.** An audit failure rolls back the write. Reads are not + audited. Audit records never contain request bodies, secrets or file contents. +- **History.** Resources from the removed copy operation keep their `admin_copy` + ownership, distinct from historical unknown ownership. + +## Out of scope + +Do not add product users, RBAC, cross-Project shared assets, administrator +execution or compatibility with old private protocols. Implementers follow the +[contributor rules](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md) and the +[Core–Runtime protocol](/runtime-protocol). + +Native failure classification is adapter-owned and uses finite, structured native +values. Optional Runtime error metadata is normalized once; it never replaces Core's +terminal authority, cancellation receipts, Usage or native identity. See [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/f45a4198aca79bf252412c55cad3647f5d704515/docs/design-principles.md) diff --git a/apps/docs/content/docs/configure.mdx b/apps/docs/content/docs/configure.mdx index 40b88980e..4ce140ad1 100644 --- a/apps/docs/content/docs/configure.mdx +++ b/apps/docs/content/docs/configure.mdx @@ -205,18 +205,20 @@ node's own files can't change its capacity, size or Runtime. ### Default models -Each harness has at most one default model provider: `protocol`, HTTPS `base_url`, -a write-only `api_key` and, for MiniMax Code, `context_window` and -`max_output_tokens`. It is the same bundle as `x_agents_core.model_provider`. Core -encrypts it with `secrets/credential.key` and never returns the key. - -New Core-hosted (`openai_hosted`) Sessions and Sessions without an environment -(`none`) use it when neither the request nor the Agent carries a provider; each -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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md#deployment-defaults). +Each harness has at most one default model configuration: + +- `model`: the provider's model ID; +- `model_provider`: the same bundle as `x_agents_core.model_provider` (`protocol`, + HTTPS `base_url`, write-only `api_key`, and for MiniMax Code `context_window` and + `max_output_tokens`); +- `harness_config`: optional native model parameters, `{}` by default. + +Core encrypts the key with `secrets/credential.key` and never returns it. Set it in +Web or with `PUT /core/v1/harnesses/{harness}/model-configuration`. + +Which Sessions use the default, and in what order it applies, is in +[Which model provider a Session uses](/user-guide#which-model-provider-a-session-uses). +Full rules: [model execution](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). diff --git a/apps/docs/content/docs/console.mdx b/apps/docs/content/docs/console.mdx index 8b5388279..f98204339 100644 --- a/apps/docs/content/docs/console.mdx +++ b/apps/docs/content/docs/console.mdx @@ -40,15 +40,8 @@ deployment sandbox nodes. Deployment sandbox management selects E2B, Docker or microsandbox; caller-managed `self_hosted` Runtimes remain a separate application path. -A Project owns one tenant and one principal. All its keys share assets and -permissions; writes record the individual key as provenance. Projects and keys -live only in PostgreSQL. Key issuance returns plaintext once and stores its digest. -Rotate by issuing another key and revoking the old one. Archive disables every key -in the Project while retaining assets and admitted work. - -The management API cannot create or edit arbitrary application resources, start -Sessions, submit input or cancel execution. Applications perform those operations -through `/v1`. Core has no API users, roles or memberships. +How Projects and keys behave, and what administrators can and cannot do, is in +the [design principles](/concepts#projects-own-assets). ## Connect and develop diff --git a/apps/docs/content/docs/examples.mdx b/apps/docs/content/docs/examples.mdx new file mode 100644 index 000000000..5e7436ebe --- /dev/null +++ b/apps/docs/content/docs/examples.mdx @@ -0,0 +1,65 @@ +--- +title: "Examples" +description: "Complete applications built on the Agents API, and what each one shows." +--- + +Complete applications built on the [Agents API](/sessions). Each one +runs against a real Core installation with a Project API key. + +| Example | What it shows | +| --- | --- | +| [Parsar Agent workbench](#parsar-agent-workbench) | A product UI: models, Skills, MCP, reusable Agents, and Sessions on any runtime | + +## Parsar Agent workbench + +A small single-user product built on Core. You save model providers, Skills and MCP +servers, combine them into Agents, then start Sessions in a managed sandbox, with +no workspace, or on your own machine. + +Source: [`example/parsar`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/README.md). + +### Run it + +You need Node 22.13+, pnpm 10.30.3, a running Core with a default model, and a Project +API key. + +```sh +export OAC_EXAMPLE_CORE_URL='https://core.example' # origin, without /v1 +export OAC_EXAMPLE_PROJECT_KEY='' +pnpm install --frozen-lockfile +pnpm --filter @oac/parsar-example dev +``` + +Open <http://127.0.0.1:18180>. The example [README](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/README.md) covers +storage, a production build, tests and connecting your own machine. + +### What to look at + +Each feature maps to one part of the API. Read the code next to the guide section: + +| Feature | API used | Guide | Code | +| --- | --- | --- | --- | +| Server-side key and headers | Bearer key, `OpenAI-Beta`, route allowlist | [Before you start](/sessions#before-you-start) | [`server.mjs`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/server.mjs) | +| Agents with a harness and model | `x_agents_core.harness`, `model_provider` | [Core extensions](/sessions#core-extensions-x_agents_core) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/server/sessions.mjs) | +| Sessions on three runtimes | `openai_hosted`, `none`, `self_hosted` with `workspace_directory` | [Create a Session](/sessions#create-a-session) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/server/sessions.mjs) | +| Crash-safe Session creation | `Idempotency-Key`, recovery from a lost response | [Idempotency](/sessions#idempotency) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/server/sessions.mjs) | +| Live replies | Event stream, text deltas, reconnect and reconcile | [Stream events](/sessions#stream-events) | [`src/lib/live-session.ts`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/src/lib/live-session.ts) | +| Follow-ups and cancel | Input events with idempotency keys | [Send input](/sessions#send-input) | [`src/Composer.tsx`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/src/Composer.tsx) | +| History | Paging Turns and Items | [Pagination](/sessions#pagination) | [`src/lib/api.ts`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/src/lib/api.ts) | +| Skills and versions | `/skills`, default version | [Skills](/sessions#skills) | [`src/Skills.tsx`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/src/Skills.tsx) | +| Connect your own machine | Environment status, executor credential | [Self-hosted execution](/self-hosted-execution) | [`src/ConnectMachine.tsx`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/parsar/src/ConnectMachine.tsx) | + +### Not covered + +Vaults and MCP authentication, OAuth, Session deletion, and MiniMax Code on your +own machine. + +## Add an example + +Put it in its own directory under [`example/`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/example/README.md) with a README +covering how to run it and which API features it shows, then add a row to the +table above. Keep examples on the public API with a Project API key: never the Core +key or private routes. Repository rules for examples are in +[CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md#repository-boundary). + +[Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/examples.md) diff --git a/apps/docs/content/docs/execution-model.mdx b/apps/docs/content/docs/execution-model.mdx index 5d59dcddf..76ccabb32 100644 --- a/apps/docs/content/docs/execution-model.mdx +++ b/apps/docs/content/docs/execution-model.mdx @@ -58,18 +58,9 @@ grant a browser execution authority. | Core API and PostgreSQL | Project isolation, resource state, deletion preconditions, audit and scheduling | | Runtime and native adapters | Existing allocation, process lifecycle and execution protocols | -A Project owns one tenant and one principal; its keys have equal access to its -assets. Projects and keys are database records. Configuration contains deployment -settings, not business identities. Core has no separate API-user or role model. - -Revoking one key prevents new authentication without removing assets or admitted -work. Archiving a Project disables all its keys and retains resources for -administrator inspection and deletion. - -Management adds no execution path. It can inspect metadata and history and apply -existing deletion rules. It cannot edit arbitrary resources, create Sessions, send -input or cancel work. A deletion conflict cannot be resolved by an implicit -cancellation from the console. +Projects, keys and administrator authority follow the +[design principles](/concepts#projects-own-assets). The console adds +no execution path: a deletion conflict is never resolved by an implicit cancellation. Secret fields remain write-only; Skill source and Artifact content have explicit read routes, while Source File content does not have an administrator download diff --git a/apps/docs/content/docs/hosted-providers.mdx b/apps/docs/content/docs/hosted-providers.mdx index 87491b15b..abd1c09d7 100644 --- a/apps/docs/content/docs/hosted-providers.mdx +++ b/apps/docs/content/docs/hosted-providers.mdx @@ -23,7 +23,7 @@ node protocol, manual registration, placement and failure handling. With the default online installation, nodes follow HTTPS redirects to download their matching Runtime and provider files directly from the release, verifying sizes and SHA-256 checksums before use. Core and Web do not download these files. - For nodes without release access, use the [offline bundle](/install#download-a-release) + For nodes without release access, use the [offline bundle](/install#installer-options) on the Web host so it serves the files locally. Verified local files are reused. - **A sandbox backend is chosen.** The installer selects microsandbox unless you chose otherwise. After `--sandbox none`, the **Nodes** page first asks you to choose @@ -241,12 +241,10 @@ WebSocket doesn't pass the reverse proxy. ## Change the sandbox backend or size -Changing backend type requires an explicit reset. Same-provider Docker and -microsandbox size or Runtime edits advance the target generation without retiring -nodes or moving existing Sessions. Version 2 nodes prepare the target independently; -existing allocations and suspended VMs keep their original generation. A qualified -older serving generation can still accept new Sessions when it has capacity, -including while a newer target is preparing or has failed. +Change the backend or sandbox size in Web under **System** → **Sandbox backend**. +What each change does, and when it needs a reset, is in +[Sandbox deployment](/configure#sandbox-deployment). This section covers +only what happens on the nodes. Node program version updates are not supported. `--update` refuses without changing node state. Preserve an older installation and its Runtime data; provision a fresh diff --git a/apps/docs/content/docs/index.mdx b/apps/docs/content/docs/index.mdx index a4111b092..5bf243458 100644 --- a/apps/docs/content/docs/index.mdx +++ b/apps/docs/content/docs/index.mdx @@ -3,42 +3,41 @@ title: "OpenAgentCore documentation" description: "Install Core and Web, create a Project API key, and add execution capacity." --- -Start with the path that matches your role. These pages are the canonical sources -for the documentation website; generated site pages are not a second manual. +OpenAgentCore runs AI agents on your own infrastructure behind the OpenAI Agents +API. Pick the path that matches your role. New here? Read the +[architecture overview](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/architecture.md) first. -## First installation and first task +## Operators: install and run -1. [Install Core and Web](/install), then sign in with the Core key. -2. [Add managed execution capacity](/hosted-providers) or - [connect your own Runtime](/self-hosted-execution). -3. Issue a Project API key and follow the [first Session walkthrough](/quickstart). -4. Continue with the [user guide](/user-guide) for capabilities, files and recovery. +1. [Install Core and Web](/install) and sign in. +2. Add execution capacity: [managed nodes or E2B](/hosted-providers), or + [your own machine](/self-hosted-execution). +3. Issue a Project API key and hand it to the application developer. -## Operate a deployment +| Guide | Covers | +| --- | --- | +| [Installation](/install) | Prerequisites, HTTPS, first sign-in, advanced options | +| [Configuration](/configure) | `config.json`, default models, sandbox deployment | +| [Nodes](/hosted-providers) | Adding, checking and removing managed nodes | +| [Self-hosted execution](/self-hosted-execution) | Connecting your own machine to a Session | +| [Native Runtime](/self-hosted-native) | Platforms, installing and operating `oac-daemon` | +| [Operations](/troubleshooting) | Services, backups, keys, repair and troubleshooting | +| [Web console](/console) | What the console shows and manages | + +## Application developers: build on the API -| Guide | Use it for | +| Guide | Covers | | --- | --- | -| [Installation](/install) | Host prerequisites, release bundles, HTTPS and first sign-in | -| [Configuration](/configure) | Installer configuration and database-owned settings | -| [Nodes](/hosted-providers) | Managed capacity, readiness and removal | -| [Self-hosted execution](/self-hosted-execution) | Connecting a user-owned machine to a Session | -| [Native daemon](/self-hosted-native) | Platform support and local installation lifecycle | -| [Operations](/troubleshooting) | Service lifecycle, backups, keys, repair and troubleshooting | -| [Administrator console](/console) | Monitoring and managing Core through Web | - -## Build an application - -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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md) to check operation support -and Harness differences before relying on an optional feature. - -## Extend Core - -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/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.md); distribution and release procedures live in -[the maintainer guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/maintainers.md). +| [Quickstart](/quickstart) | From a Project API key to a finished Session | +| [User guide](/user-guide) | Common tasks: harness and model choice, follow-ups, capabilities, files, cancel | +| [Agents API guide](/sessions) | Every resource, with SDK and HTTP examples | +| [Examples](/examples) | Complete applications built on the API | +| [API index](/public-api) | All three namespaces and their credentials | + +## Contributors: extend Core + +Start with the [developer guide](/development): repository map, local setup, +and how to add a Sandbox Provider, a harness or a Runtime feature. Repository rules +are in [CONTRIBUTING.md](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/CONTRIBUTING.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.mdx b/apps/docs/content/docs/install.mdx index 4d3a39342..292b61028 100644 --- a/apps/docs/content/docs/install.mdx +++ b/apps/docs/content/docs/install.mdx @@ -4,20 +4,21 @@ description: "Current distribution, host prerequisites, HTTPS, first sign-in and --- One command installs Core, the Web console and PostgreSQL on a Linux host. Web is -the administrator console: you sign in with the Core key, issue Project API keys and -add nodes. Applications call Core's API with those keys. +the administrator console: you sign in with the Core key, issue Project API keys +and add nodes. Applications then call Core's API with those keys. + +The default path has five steps: 1. [Check the prerequisites](#prerequisites). -2. [Download a release bundle](#download-a-release). -3. [Run the installer](#install). -4. [Put Core and Web behind HTTPS](#https-and-the-reverse-proxy), or - [try it locally first](#try-it-locally-with-a-quick-tunnel). -5. [Sign in to Web and issue a key](#sign-in-to-web). -6. [Add a node](/hosted-providers). +2. [Run the installer](#install). +3. [Make Core reachable](#make-core-reachable) over HTTPS, or through a quick tunnel + for a trial. +4. [Sign in to Web](#sign-in-to-web), set a default model and issue a key. +5. [Add execution capacity](#next-steps): a node, E2B or your own machine. -These pages describe the current source. Every bundle carries the docs that match it -under `docs/`. Core supports fresh installation and repair of the -same release; historical-version upgrades and conversion are unsupported. +Every flag, listener addresses and ports are in +[installation options](/install-options). Offline hosts, other sandbox backends +and split deployments are in [Advanced installation](#advanced-installation). ## Prerequisites @@ -25,160 +26,288 @@ same release; historical-version upgrades and conversion are unsupported. - Linux amd64 with Python 3.9 or newer. - Docker Engine with Docker Compose 2.26.0 or newer (`docker compose version`). -- An account that can run `docker` and write to the installation directory. Both - ordinary users and root are supported; the installer uses the current account - without invoking sudo, switching accounts or changing Docker permissions. +- An account that can run `docker` and write to its home directory. Ordinary users + and root both work; the installer never calls sudo. - Free loopback ports 8091 (Core) and 8080 (Web), or [custom listeners](/install-options#listeners-and-access). -- curl to fetch the installation script; no GitHub CLI or login is required. +- curl. No GitHub CLI or login is needed. + +The Core host needs no KVM. + +**A public HTTPS address**, such as `https://core.example`, with a DNS name and a +TLS certificate. Nodes, E2B sandboxes and self-hosted machines reach Core there. A +local trial can skip it and [set it later](#make-core-reachable). + +## Install + +```sh +curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash +``` -The Core host needs no KVM and no systemd user services, unless you choose -[native Core](#native-core). +For an HTTPS deployment, pass the public address: -**Network, for nodes and remote access** +```sh +curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash -s -- --public-url https://core.example +``` -- A DNS name for Core and Web, such as `core.example`, with a TLS certificate. -- A reverse proxy on the Core host that sends three routes to the right service; see - [HTTPS and the reverse proxy](#https-and-the-reverse-proxy). +The script picks the latest stable release, verifies its checksum and runs the +bundled installer, which: -Node hosts and their sandboxes, E2B sandboxes and self-hosted executors all reach -Core at this HTTPS address. A local trial needs none of this: install without a -public URL and set it later. +1. checks the host and loads the Core, Web and PostgreSQL images; +2. creates `~/.oac/core` (mode `0700`) with the Core key, `config.json` and the + `oac` management command; +3. starts PostgreSQL, Core and Web with Docker Compose, on their configured listeners + (loopback by default); +4. selects the microsandbox backend at the Standard size. It adds no node. -## Download a release +It creates no Project or key and makes no model request. It ends by printing the +console address, the API base URL and the next steps. -Every Release includes a standalone [install.sh](https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh). -It selects the latest published stable release by default, downloads that release's -control-plane bundle and checksum, verifies the archive, and runs its bundled installer. -This installs Core, Web and PostgreSQL without downloading Runtime images or node -execution files. Nodes download those separately when they are added. -You do not need to find a tag, commit SHA or archive filename. +Without `--public-url`, only this host can reach the installation: by default Web at +`http://127.0.0.1:8080` and the API at `http://127.0.0.1:8091/v1`. To listen on other +addresses or ports, see [installation options](/install-options#listeners-and-access). -## Install +## Make Core reachable -Install the latest stable release: +Nodes, E2B and self-hosted machines need a public HTTPS address. Choose one: + +| Option | Use it for | +| --- | --- | +| [HTTPS and the reverse proxy](#https-and-the-reverse-proxy) | Any lasting installation | +| [A quick tunnel](#try-it-locally-with-a-quick-tunnel) | A trial without DNS or certificates | + +Then set the address, if you didn't pass `--public-url`: ```sh -curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash +# in ~/.oac/core/config.json: "public_url": "https://core.example" +~/.oac/core/oac apply ``` -For an HTTPS deployment, pass the public address: +Core derives every address it hands out from `public_url`. To change it later, see +[Changing the public URL](/configure#changing-the-public-url). + +### HTTPS and the reverse proxy + +Core and Web share one public origin. Your reverse proxy terminates TLS and routes +by path: + +| Path | Goes to | Callers | +| --- | --- | --- | +| `/v1`, `/v1/*` | Core, `127.0.0.1:8091` by default | Applications, with a Project API key | +| `/api/v1/*` | Core, `127.0.0.1:8091` | Nodes, sandboxes and self-hosted machines. Uses WebSockets | +| Everything else | Web, `127.0.0.1:8080` by default | Browsers, and node installers at `/node-install/*` | + +The proxy must: + +- **Preserve Host.** Web accepts only the host of its public URL. +- **Pass WebSocket upgrades** on `/api/v1`. +- **Not buffer or time out streams.** `/v1` streams Session events. +- **Accept large uploads.** Source files may reach 512 MiB; Core enforces the limits. + +Run the proxy on the Core host when Core and Web listen on loopback (the default). +`oac status` prints these routes with your addresses and ports. + +**Caddy** obtains the certificate itself and passes Host and WebSockets by default: + +```text +core.example { + @core path /v1 /v1/* /api/v1/* + handle @core { + reverse_proxy 127.0.0.1:8091 + } + handle { + reverse_proxy 127.0.0.1:8080 + } +} +``` + +**nginx**, for example in `/etc/nginx/conf.d/oac.conf` inside the `http` block: + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + server_name core.example; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name core.example; + ssl_certificate /etc/letsencrypt/live/core.example/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/core.example/privkey.pem; + + client_max_body_size 0; # Core enforces its own upload limits + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_buffering off; # server-sent events on /v1 + proxy_request_buffering off; + proxy_read_timeout 1h; # long-lived WebSockets and streams + proxy_send_timeout 1h; + + location = /v1 { proxy_pass http://127.0.0.1:8091; } + location /v1/ { proxy_pass http://127.0.0.1:8091; } + location /api/v1/ { proxy_pass http://127.0.0.1:8091; } + location / { proxy_pass http://127.0.0.1:8080; } +} +``` + +Check the routing: ```sh -curl -fsSL https://github.com/MiniMax-AI/parsar-core/releases/latest/download/install.sh | bash -s -- --public-url https://core.example +curl -s -o /dev/null -w '%{http_code}\n' -H 'OpenAI-Beta: agents=v1' https://core.example/v1/agents +``` + +`401` means `/v1` reached Core, which asks for a key. `404` means it reached Web: +fix the proxy, or application calls and every node connection will fail. + +TLS verification stays on everywhere. With a private certificate authority, node +hosts, self-hosted machines and the Runtime image must trust it. + +### Try it locally with a quick tunnel + +A [Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) +gives a trial installation a temporary public HTTPS address. It forwards to one +port, so put a local proxy with the same routes in front: + +```text +http://:8443 { + bind 127.0.0.1 + @core path /v1 /v1/* /api/v1/* + handle @core { + reverse_proxy 127.0.0.1:8091 + } + handle { + reverse_proxy 127.0.0.1:8080 + } +} ``` -To select a version, add `--version v1.2.3` after `bash -s --`. Explicit versions -may include prereleases; the default never selects one. Other arguments go unchanged -to the bundled installer. You can also download `install.sh` from the Release page -and run `bash install.sh --version v1.2.3`. The examples below use this saved script -or the bundle's existing `./install.sh`. +1. Start the proxy: `caddy run --config Caddyfile`. +2. Start the tunnel: `cloudflared tunnel --url http://127.0.0.1:8443`. It prints an + address such as `https://random-words.trycloudflare.com`. +3. Set that address as `public_url` in `~/.oac/core/config.json` and run + `~/.oac/core/oac apply`. -The downloader resolves the release once, verifies SHA-256 before extraction, and -retains the verified bundle under `~/.oac/releases/` for repair. It never replaces -an existing installation or upgrades it. To repair an installed version, select -that same version explicitly. The bundled installer also checks its own -`SHA256SUMS` before changing installation state. +The address changes whenever `cloudflared` restarts; nodes bound to the old address +must then be added again. Throughput is low, so a node's first Runtime download +(about 500 MB) can be slow; see [slow links](/hosted-providers#rerun-expiry-and-slow-links). -For machines without GitHub access, transfer the Release's -`*-linux-amd64-offline.tar.gz` and matching `.sha256` file, verify and extract -them locally, then run the bundled `./install.sh`. This explicitly includes node and -Runtime files so Web can serve them without release access. The default online -installation uses the smaller archive and leaves those downloads to the nodes. +## Sign in to Web -The installer prints each stage before it starts, including image preparation and -service startup. Its final summary groups access addresses, sign-in details, -next steps and management commands. Colors are enabled only in a terminal; set -`NO_COLOR=1` to disable them. Redirected output stays plain text. A failed step -stops installation and never prints a successful completion message. A no-change -repair checks installation settings without rechecking health; use `oac status` -to inspect service health. +1. **Open the console** at the address the installer printed: your public URL, or + `http://127.0.0.1:8080` on the Core host by default. Web refuses other host names. + For a remote host without a public URL, forward the port over SSH first, for + example `ssh -L 8080:127.0.0.1:8080 `. +2. **Sign in with the Core key**, the installation's administrator credential. Web has + no user accounts. See [Core key](/troubleshooting#core-key). -The installer: + ```sh + cat ~/.oac/core/secrets/core.key + ``` -1. checks the host and the bundle, and loads the Core, Web and PostgreSQL images; -2. creates private `~/.oac` (mode `0700`) and the installation directory `~/.oac/core` with the Core key, `config.json` - and the `oac` command ([what it creates](#what-the-installer-creates)); -3. starts PostgreSQL, Core and Web with Docker Compose, on loopback ports only; -4. selects microsandbox at Web's Standard size (2 CPUs, 4 GiB memory and two 8 GiB - disks each). It adds no node, so this host needs no KVM; you add nodes in Web. +3. **Set a default model.** On **System**, find **Default model**. On the card marked + **Default** (Codex unless you changed it), choose **Set** and enter the model and + its provider's base URL and API key. MiniMax Code also needs the context window + and max output tokens. See [Default models](/configure#default-models). +4. **Create a project and issue a key.** On **Projects and keys**, choose + **Create project**, then **Issue key**. The dialog shows the key once: copy it and + keep it safe. Its **How to call** card shows the API base URL and sample requests. +5. **Hand over** the key and the API base URL to the application developer. They continue with the [quickstart](/quickstart). -It creates no Project or API key, makes no model request and runs no sample task. -It ends by printing the console address, the API base URL and the next steps. +Web's **Overview** tracks these steps in a **Getting started** checklist. -Without `--public-url`, the installation uses its configured loopback addresses. -See [listener configuration](/install-options#listeners-and-access). Set -`public_url` in `config.json` later and run `oac apply`; you don't reinstall. Nodes, -E2B and self-hosted executors need the public URL. +## Next steps -### Installation choices +| Goal | Guide | +| --- | --- | +| Run Sessions in managed sandboxes | [Add a node](/hosted-providers), or use [E2B](#sandbox-backend) | +| Run your first Session | [Quickstart](/quickstart) | +| Run Sessions on your own machine | [Self-hosted execution](/self-hosted-execution) | +| Operate the installation | [Operations](/troubleshooting) and [configuration](/configure) | -For flags, listener addresses and custom ports, see [Installation options](/install-options). +## Advanced installation -#### Sandbox backend +### Installer options + +Every flag, with the `config.json` field it seeds, is in +[installation options](/install-options). Pass them after `bash -s --`, or +download `install.sh` from the Release page and run it directly. The script +verifies the bundle's SHA-256 before extracting it and keeps the verified bundle +under `~/.oac/releases/` for repair. It never upgrades an existing installation. + +**Offline hosts.** Transfer the Release's `*-linux-amd64-offline.tar.gz` and its +`.sha256` file, verify and extract them, then run the bundled `./install.sh`. The +offline bundle also carries the node and Runtime files, so Web can serve them to +nodes without release access. + +**Output.** The installer prints each stage, then a summary of addresses, sign-in +details and next steps. Set `NO_COLOR=1` to disable colors. A failed step stops +installation without a success message. + +### Sandbox backend A deployment runs its sandboxes on exactly one backend: | `--sandbox` | Sandboxes run on | You then | | --- | --- | --- | -| `microsandbox` (default) | microVMs on your nodes (KVM), 2 CPUs, 4 GiB memory and two 8 GiB disks each | [Add nodes](/hosted-providers) in Web | -| `docker` | Docker on your nodes, 2 CPUs and 2 GiB each; weaker isolation, confirmed at install | [Add nodes](/hosted-providers) in Web | -| `e2b` | E2B's cloud, with the CPU and memory of your template build | Nothing: E2B needs no nodes | -| `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/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 -running, and you choose the backend on the Nodes page. - -`--sandbox docker` first prints Docker's drawbacks. Containers share the host kernel, -so a container escape reaches the node host, while microsandbox runs each sandbox in -its own microVM. The node service account in the `docker` group is root-equivalent -on each node host. Choose Docker only for trusted workloads or hosts without KVM. -The installer then asks for confirmation, defaulting to No; without a terminal, pass -`--accept-docker-risks`. Unconfirmed, it exits with an error before it installs -anything. - -E2B also needs an HTTPS public URL that is not loopback, because E2B's sandboxes -call Core from E2B's cloud. The installer refuses `--sandbox e2b` without one, before -it installs anything: +| `microsandbox` (default) | microVMs on your nodes (KVM): 2 CPUs, 4 GiB memory and two 8 GiB disks each | [Add nodes](/hosted-providers) in Web | +| `docker` | Docker on your nodes: 2 CPUs and 2 GiB each; weaker isolation | [Add nodes](/hosted-providers) in Web | +| `e2b` | E2B's cloud, sized by your template build | Nothing: E2B needs no nodes | +| `none` | Nothing yet | Choose on the **Nodes** page in Web | + +The Standard sizes come from Web's +[`standard-sizes.json`](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/apps/web/src/features/sandbox/standard-sizes.json). If +Core refuses the choice, for example because E2B rejects the key, the installer +prints Core's message and exits; the services keep running and you choose the +backend in Web. To change the backend or size later, see +[Sandbox deployment](/configure#sandbox-deployment). + +**Docker's risks.** Containers share the host kernel, so a container escape reaches +the node host; microsandbox gives each sandbox its own microVM. The node's service +account in the `docker` group is root-equivalent. Choose Docker only for trusted +workloads or hosts without KVM. The installer asks for confirmation (default No); +without a terminal, pass `--accept-docker-risks`. + +**E2B** needs a public HTTPS URL that is not loopback, because E2B's sandboxes call +Core from E2B's cloud. Prepare the template build with the +[E2B guide](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/services/agents-api/deploy/e2b/README.md), then: ```sh ./install.sh --public-url https://core.example --sandbox e2b \ --e2b-api-key-file "$HOME/.oac/e2b-api-key" --e2b-template ':' ``` -Prepare the template build with the -[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). - -#### Modes +### Modes | Mode | Runs | Use it for | | --- | --- | --- | | all (default) | PostgreSQL, Core and Web | Most installations | -| `--core-only` | PostgreSQL and Core | A Core whose Web runs on another host, or scripts only. Without Web there is no Add node command | +| `--core-only` | PostgreSQL and Core | A Core whose Web runs elsewhere, or scripts only. No Add node command | | `--web-only` | Web | A second host for the console, paired with an existing Core | -A Web-only console forwards every signed-in `/core/v1` request to its Core with the -Core key, so `--core-url` must reach Core's `/core/v1` directly. The default reverse -proxy sends `/core/v1` to Web, so the Core's public URL doesn't work here: +The mode and native Core are fixed once installed; to change them, install into a +new directory. + +A Web-only console forwards signed-in `/core/v1` requests to its Core with the Core +key, so `--core-url` must reach Core's `/core/v1` directly. The public URL doesn't, +because the default proxy sends `/core/v1` to Web: -- **Web on the Core host:** use Core's loopback port, - `--core-url http://127.0.0.1:8091`. -- **Web on another host:** give Core a second HTTPS name whose proxy sends every path to - Core, such as `https://core-api.example` to `127.0.0.1:8091` on the Core host, and use - it as `--core-url`. Allow only the Web host's address on that name; anyone else who - reaches it still needs the Core key. +- **Web on the Core host:** use `--core-url http://127.0.0.1:8091`. +- **Web on another host:** give Core a second HTTPS name that sends every path to + Core, such as `https://core-api.example`, and allow only the Web host's address. -##### Split deployment +#### Split deployment | Host | Install | Reverse proxy | | --- | --- | --- | -| Core | `./install.sh --core-only --public-url https://core.example` | `core.example`: `/v1`, `/v1/*` and `/api/v1/*` to Core; `/node-install/*` to the Web host, with Host rewritten to `console.example`; nothing else. `core-api.example`: every path to Core, for the Web host's address only | +| Core | `./install.sh --core-only --public-url https://core.example` | `core.example`: `/v1`, `/v1/*` and `/api/v1/*` to Core; `/node-install/*` to the Web host with Host rewritten to `console.example`; nothing else. `core-api.example`: every path to Core, for the Web host's address only | | Web | `./install.sh --web-only …`, below | `console.example`: every path to Web | ```sh @@ -188,16 +317,13 @@ proxy sends `/core/v1` to Web, so the Core's public URL doesn't work here: --core-key-file "$HOME/core.key" ``` -Browsers use `console.example`, and nodes download their installer from it. -Applications, nodes and sandboxes call Core at `core.example`, and self-hosted -executors download their installer from there too, which is why `core.example` sends -`/node-install/*` to the Web host. Web serves those files only for its own name, so the -proxy rewrites Host. Web serves bootstrap metadata and any locally available node -artifacts. Missing artifacts redirect to the matching release and download directly -on the node; the Web host does not fetch the Runtime image. For disconnected nodes, -install Web from the offline bundle (or add its verified `artifacts/`). +Browsers and node installers use `console.example`. Applications, nodes, sandboxes +and self-hosted machines call Core at `core.example`; self-hosted machines also +download their installer there, which is why `core.example` forwards +`/node-install/*` to Web. Missing node artifacts redirect to the release; for +disconnected nodes, install Web from the offline bundle. -Caddy on the Core host, where `203.0.113.10` stands for the Web host's address: +Caddy on the Core host, where `203.0.113.10` is the Web host's address: ```text core.example { @@ -280,198 +406,20 @@ server { The Web host's proxy sends every path to Web, for example `console.example { reverse_proxy 127.0.0.1:8080 }` in Caddy. -Copy the key file from the Core host's `secrets/core.key` with mode `0600`; the -installer keeps its own copy in `secrets/core.key`, so delete `$HOME/core.key` -afterwards. After the Core key is rotated, copy the new key again; see -[Rotate the Core key](/troubleshooting#rotate-the-core-key). A Web-only install selects no -sandbox backend: the Core host's `--sandbox` does, or later the paired console's -**Nodes** page. - -The mode and native Core are fixed once installed. To change them, install into a -new directory. - -#### Native Core - -`--native-core` runs Core as a systemd user service of the installing user; -PostgreSQL and Web stay in containers. It needs a running systemd user manager and -lingering for that user (`sudo loginctl enable-linger "$USER"`), and the bundle's -native binaries must load on the host. PostgreSQL then listens on a loopback port -the installer picks (`ports.database`), and Web uses the host network. Native Core -needs no KVM and is unrelated to the sandbox backend. - -## HTTPS and the reverse proxy - -By default, Core and Web share one public origin; for Web on its own host, see the -[split deployment](#split-deployment). Your reverse proxy terminates TLS and routes by -path: - -| Path | Goes to | Callers | -| --- | --- | --- | -| `/v1`, `/v1/*` | Core, `127.0.0.1:8091` | Applications, with a Project API key | -| `/api/v1/*` | Core, `127.0.0.1:8091` | Nodes, sandboxes and self-hosted executors, with their own machine credentials. Uses WebSockets | -| Everything else | Web, `127.0.0.1:8080` | Browsers: the console, its sign-in and `/core/v1/*`. Node and executor hosts download their installers from `/node-install/*` | - -The proxy must: - -- **Preserve Host.** Web accepts only requests for the host of its public URL. -- **Pass WebSocket upgrades** on `/api/v1`. Nodes and Runtime daemons hold long-lived - WebSocket connections. -- **Not buffer or time out streams.** `/v1` streams Session events (server-sent events). -- **Accept large uploads.** Core enforces its own limits; source files may reach - 512 MiB. - -Web answers 404 on `/v1` and `/api/v1` and never forwards them. If those paths reach -Web, application calls, node enrollment and every sandbox connection fail. Run the -proxy on the Core host, since Core and Web listen on loopback. `oac status` prints -the routes with this installation's ports. - -**Caddy** (obtains and renews the certificate itself; passes Host and WebSockets by -default): - -```text -core.example { - @core path /v1 /v1/* /api/v1/* - handle @core { - reverse_proxy 127.0.0.1:8091 - } - handle { - reverse_proxy 127.0.0.1:8080 - } -} -``` - -**nginx** (for example `/etc/nginx/conf.d/oac.conf`, inside the `http` block; -use your certificate paths): - -```nginx -map $http_upgrade $connection_upgrade { - default upgrade; - '' close; -} - -server { - listen 80; - server_name core.example; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - server_name core.example; - ssl_certificate /etc/letsencrypt/live/core.example/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/core.example/privkey.pem; - - client_max_body_size 0; # Core enforces its own upload limits - proxy_http_version 1.1; - proxy_set_header Host $http_host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_buffering off; # server-sent events on /v1 - proxy_request_buffering off; - proxy_read_timeout 1h; # long-lived WebSockets and streams - proxy_send_timeout 1h; - - location = /v1 { proxy_pass http://127.0.0.1:8091; } - location /v1/ { proxy_pass http://127.0.0.1:8091; } - location /api/v1/ { proxy_pass http://127.0.0.1:8091; } - location / { proxy_pass http://127.0.0.1:8080; } -} -``` - -Replace `core.example` and, if you changed them, the ports. To check the routing: - -```sh -curl -s -o /dev/null -w '%{http_code}\n' -H 'OpenAI-Beta: agents=v1' https://core.example/v1/agents -``` - -`401` means `/v1` reached Core, which asks for a key; `404` means it reached Web. - -Install with `--public-url https://core.example`, or, for an existing installation, -set `public_url` in `~/.oac/core/config.json` and run `~/.oac/core/oac apply`. -Core derives every address it hands out from this one setting. If you change it while -nodes, sandboxes or self-hosted executors use the old address, `oac apply` lists -them and asks you to confirm; those nodes must then be added again. See -[Changing the public URL](/configure#changing-the-public-url). - -TLS verification stays on everywhere. With a private certificate authority, node -hosts, executor hosts and the Runtime image must trust it. - -## Try it locally with a quick tunnel - -For a trial without DNS or certificates, a -[Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) -gives the installation a temporary public HTTPS address. It forwards to one local -port, so put a plain-HTTP proxy with the same three routes in front, for example this -Caddyfile on `127.0.0.1:8443`: - -```text -http://:8443 { - bind 127.0.0.1 - @core path /v1 /v1/* /api/v1/* - handle @core { - reverse_proxy 127.0.0.1:8091 - } - handle { - reverse_proxy 127.0.0.1:8080 - } -} -``` +Copy `secrets/core.key` from the Core host with mode `0600`, then delete +`$HOME/core.key`; the installer keeps its own copy. After a +[Core key rotation](/troubleshooting#rotate-the-core-key), copy it again. A Web-only +install selects no sandbox backend. -1. Install, with or without a public URL (`./install.sh`). -2. Start the local proxy: `caddy run --config Caddyfile`. -3. Start the tunnel: `cloudflared tunnel --url http://127.0.0.1:8443`. It prints an - address such as `https://random-words.trycloudflare.com`. -4. Set `"public_url": "https://random-words.trycloudflare.com"` in - `~/.oac/core/config.json` and run `~/.oac/core/oac apply`. -5. Open that address and [sign in](#sign-in-to-web). +### Native Core -A quick tunnel is for trials only. Its address changes whenever `cloudflared` -restarts; nodes and executors bound to the old address must then be added again. -Its throughput is low, so the first node download of the Runtime (about 500 MB) can -be slow; see [slow links](/hosted-providers#rerun-expiry-and-slow-links). Nodes and E2B need a -reachable HTTPS address, so a loopback-only installation can't have nodes: Web says so -at Add node. +`--native-core` runs Core as a systemd user service; PostgreSQL and Web stay in +containers. It needs a running systemd user manager with lingering +(`sudo loginctl enable-linger "$USER"`), and the bundle's native binaries must load +on the host. PostgreSQL then listens on a loopback port the installer picks +(`ports.database`). Native Core is unrelated to the sandbox backend. -## Sign in to Web - -1. Open the console address the installer printed. Use exactly that address; Web - refuses other host names. For a loopback installation on a remote machine, - forward the configured address and port through SSH first. -2. Sign in with the Core key: - - ```sh - cat ~/.oac/core/secrets/core.key - ``` - - The Core key is the installation's administrator credential. Keep it private; see - [Core key](/troubleshooting#core-key). Web has no user accounts. -3. **Set a default model.** Open **System** and find **Default model**. On the harness - card marked **Default** (Codex unless you changed `core.default_harness`), choose - **Set**; once a provider is configured, the button reads **Replace**. Enter the - model provider's base URL and API key; MiniMax Code also needs the context window - and max output tokens. Core encrypts the key and never shows it again. The default - applies to Core-hosted Sessions and Sessions without an environment when the request - and the Agent carry no model provider; self-hosted Sessions never use it. See - [model providers](/quickstart#model-providers). -4. **Create a project and issue a key.** Open **Projects and keys**, choose - **Create project** and give it a **Name**, then **Issue key** in it with a - **Key name**. The **Key issued** dialog shows the key once: choose **Copy key**, keep - it somewhere safe, then **I've saved this key**. Core keeps only a digest. The - dialog's **How to call** card shows the API base URL and sample requests. -5. Give the application developer the key, the API base URL and the model ID to use - with the default model provider (Sessions must name `agent.model`). They follow the - [API quickstart](/quickstart). - -**Overview** tracks the setup in a **Getting started** checklist, in any order: -**Get sandboxes ready** ([add a node](/hosted-providers)), **Set a default model**, -**Create a project and issue a key**, and **Run the first Session**. After you hide it, -**Show Getting started** in the sidebar brings it back. - -An existing pre-rename installation at `~/.parsar/core` blocks a new default install. -Historical conversion is not supported. Preserve the existing installation and explicitly -choose another `--install-dir`. See [installation version policy](/troubleshooting#installation-version-policy). - -## What the installer creates +### What the installer creates The installation directory, `~/.oac/core` by default, mode `0700`: @@ -482,32 +430,29 @@ The installation directory, `~/.oac/core` by default, mode `0700`: | `secrets/core.key` | The Core key | | `secrets/credential.key` | Encryption key for credentials stored in the database. Back it up with the database; never replace it | | `secrets/database.password` | PostgreSQL password | -| `state.json` | Format 2, installation ID, Compose project name, image IDs and source commit. Written by the tools only | -| `generated/` | Files derived from `config.json`: `compose.json`, `core.env`, `core-key-digests.json`, `settings.json`, `config.schema.json`, and `runtime-history.json` or the native Core unit when used. `oac apply` rewrites them; don't edit them | -| `node-payload/` | The managed node installer, the manifest and the node files that Web serves at `/node-install/` | +| `state.json` | Installation ID, Compose project name, image IDs and source commit. Written by the tools only | +| `generated/` | Files derived from `config.json`. `oac apply` rewrites them; don't edit them | +| `node-payload/` | The node installer and files that Web serves at `/node-install/` | | `state/e2b/` | Private E2B receipts | | `native/` | Core binaries, with `--native-core` only | -Web-only installations have only `secrets/core.key` among the secrets, and no -`state/e2b/`; Core-only installations have no `node-payload/`. - -In Docker, the installer creates a Compose project named `oac-<10 hex digits>` -(`project` in `state.json`) with the containers `database`, `migrate` (runs the -migrations, then exits), `core` and `web`, and the volume `_database` that -holds all data. Core and Web publish their configured listeners. The database -publishes no port unless Core is native, when it remains on loopback. +Web-only installations have only `secrets/core.key` among the secrets. Core-only +installations have no `node-payload/`. -The database holds the sandbox backend selection, and later your Projects, keys, -nodes, default models and all execution history. Apart from Docker's own storage, -nothing is written outside your home directory: no system service and no file under -`/etc`. Native Core adds a systemd user unit, enabled from `generated/`. +In Docker, the Compose project is named `oac-<10 hex digits>` (`project` in +`state.json`), with the containers `database`, `migrate`, `core` and `web` and the +volume `_database` that holds all data. Apart from Docker's storage, +nothing is written outside your home directory. Native Core adds a systemd user +unit. -## Rerun the installer +### Rerun the installer Rerunning `./install.sh` from the same bundle repairs an installation: it reloads -missing images, restores a missing `oac` command, copies node files newly placed in -`artifacts/`, applies `config.json` and starts the services. It accepts only -`--install-dir`. It refuses a bundle from another release; see -[installation version policy](/troubleshooting#installation-version-policy). +missing images, restores the `oac` command, applies `config.json` and starts the +services. It accepts only `--install-dir` and refuses a bundle from another +release; see [installation version policy](/troubleshooting#installation-version-policy). + +An installation from before the rename, at `~/.parsar/core`, blocks a new default +install. Keep it and choose another `--install-dir`. [Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/install.md) diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json index a9e431ad5..61da23348 100644 --- a/apps/docs/content/docs/meta.json +++ b/apps/docs/content/docs/meta.json @@ -15,6 +15,7 @@ "public-api", "agents-and-tools", "sessions", + "examples", "---Execution---", "environments-and-files", "hosted-providers", diff --git a/apps/docs/content/docs/public-api.mdx b/apps/docs/content/docs/public-api.mdx index 9dfe73f02..6fb323940 100644 --- a/apps/docs/content/docs/public-api.mdx +++ b/apps/docs/content/docs/public-api.mdx @@ -3,46 +3,67 @@ title: "API namespaces and credentials" description: "The public application API, private administration API and machine connection interface." --- -Core serves three namespaces. Protected operations authenticate their own callers; -credentials cannot be substituted across these boundaries. Versioned native -installer downloads are public release content. +Core serves three namespaces. Each has one kind of caller and its own credential; +no credential works in another namespace. Versioned native 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`, `harness_config`, Session `installation`) | [Public API](/sessions) | +| `/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`) | [Agents API guide](/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 -the Project's assets and execution principal; provenance retains the key that -performed each write. Projects and application keys live in PostgreSQL, never -deployment configuration. +A credential used in another namespace gets 401: a Project API key on `/core/v1` or +`/api/v1`, the Core key on `/v1` or `/api/v1`. How Projects and keys behave is in +[Projects own assets](/concepts#projects-own-assets). -The browser talks only to Web's server: `/console/auth` and `/console/config`, -`/node-install/*`, the static pages, and `/core/v1/*`, which the server forwards -with the Core key after sign-in and same-origin checks. Users sign in to Web with -the Core key and get an HttpOnly session cookie; the browser never receives the -key. Core decides which `/core/v1` routes -exist; Web returns 404 for `/v1` and `/api/v1`, whatever credential a request -carries. - -The deployment's reverse proxy sends `/v1`, `/v1/*` and `/api/v1/*` to Core and -every other path, including `/core/v1/*`, to Web. Operator scripts call `/core/v1` -with the Core key on Core's loopback port, not through the public entry. +**Routing.** The reverse proxy sends `/v1` and `/api/v1` to Core and everything else +to Web ([proxy setup](/install#https-and-the-reverse-proxy)). +Browsers reach `/core/v1` only through Web's server, which adds the Core key after +sign-in; Web returns 404 for `/v1` and `/api/v1`. Operator scripts call `/core/v1` +on Core's loopback port. Details: [Web and Core](/admin-api). ## Public API -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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json); the -[Public API guide](/sessions) groups them by resource. `/v1` has no -Core-only route. +Applications call `/v1` with a Project API key. The routes are exactly the 58 pairs +in [upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json). The +[Agents API guide](/sessions) explains every resource with SDK and HTTP +examples. ## Core API All routes are under `/core/v1`. Core Web's server and operator scripts call them -with the Core key. +with the Core key. Most administrators use Web instead; call the API directly for +automation. + +### Common tasks + +Run these on the Core host, against Core's loopback port. The helper reads the key +from its file, keeping it off the command line: + +```sh +core() { # core METHOD PATH [JSON body] + curl -fsS -X "$1" "http://127.0.0.1:8091/core/v1$2" \ + -H @<(printf 'Authorization: Bearer %s\n' "$(cat ~/.oac/core/secrets/core.key)") \ + -H 'Content-Type: application/json' ${3:+-d "$3"} +} +``` + +| Task | Command | +| --- | --- | +| List Projects | `core GET /projects` | +| Create a Project | `core POST /projects '{"name": "billing-bot"}'` | +| Issue an API key (shown once, as `key`) | `core POST /projects/$PROJECT_ID/keys '{"name": "prod"}'` | +| Revoke a key | `core DELETE /projects/$PROJECT_ID/keys/$KEY_ID` | +| Archive a Project (revokes all keys) | `core POST /projects/$PROJECT_ID/archive` | +| See harnesses and their default models | `core GET /harnesses` | +| Set Codex's default model | `core PUT /harnesses/codex/model-configuration '{"model": "your-model-id", "model_provider": {"protocol": "responses", "base_url": "https://provider.example/v1", "api_key": "sk-..."}}'` | +| Issue an executor credential | See [self-hosted execution](/self-hosted-execution#operator-credential-management) | +| Installation facts, including the API base URL | `core GET /installation` | + +Errors use the [Core error envelope](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-errors.md). + +### All routes | Routes | Contents | Contract | | --- | --- | --- | @@ -56,7 +77,7 @@ with the Core key. | `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/e2b/templates[/{template_id}/builds]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Core Web server or operator scripts with the Core key: sandbox deployment, read-only E2B template discovery, 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) | +| `sandbox/deployment[/reset]`, `sandbox/e2b/templates[/{template_id}/builds]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Sandbox deployment, read-only E2B template discovery, 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 @@ -100,19 +121,15 @@ support. The [coverage record](https://github.com/MiniMax-AI/parsar-core/blob/f4 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/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. - -### Self-hosted installation +## Self-hosted installation -Authenticated Session creation/detail responses include short-lived commands in +Creating or reading a `self_hosted` Session returns short-lived install commands in `x_agents_core.installation`. Core Web reads the same commands at `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation`. Machine installers use `POST /api/v1/agent-daemon/installation` and its `/claim` -subroute with the installation Bearer authorization. Qualified artifacts beneath -`/api/v1/agent-daemon/install/{version}/` are public, immutable release content. -See [native self-hosted installation](/self-hosted-native) for expiry, retry, -credential ownership and platform rules. +subroute with the installation Bearer authorization. Qualified artifacts under +`/api/v1/agent-daemon/install/{version}/` are public, immutable release content. See +the [native Runtime guide](/self-hosted-native) for expiry, retry, credential +ownership and platform rules. [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 fe80bb1da..32ce20a66 100644 --- a/apps/docs/content/docs/quickstart.mdx +++ b/apps/docs/content/docs/quickstart.mdx @@ -1,36 +1,42 @@ --- title: "Call the Agent API" -description: "Use the pinned SDK, a Project API key and an explicit model provider to run a Session." +description: "From a Project API key to a finished Session in three steps." --- -Before starting, [install Core and Web](/install), issue a Project API key, and -prepare a ready managed node or E2B backend. You also need Python 3.9+ and model -provider access. This walkthrough uses Codex with a Responses-compatible provider. +This walkthrough takes you from a Project API key to an agent that has created a file +and reported back. You need: -Core serves the OpenAI Agents API. Applications use the official OpenAI SDK with two -environment variables, which the SDK reads by default: +- a Project API key and the API base URL, from your administrator + ([Sign in to Web](/install#sign-in-to-web)); +- a ready node or E2B backend, so Core has somewhere to run the agent + ([Nodes](/hosted-providers)); +- Python 3.9 or newer; +- a model: either the installation's default model, set by your administrator, or + your own provider's model ID, base URL and API key. -| Variable | Value | From | -| --- | --- | --- | -| `OPENAI_BASE_URL` | The installation's API base URL: its public URL followed by `/v1`, such as `https://core.example/v1` | The administrator; Web's **System** page shows it as **API base URL** | -| `OPENAI_API_KEY` | A Project API key | The administrator issues it on **Projects and keys**; see [Sign in to Web](/install#sign-in-to-web) | +The example uses Codex. Other harnesses are covered in the +[user guide](/user-guide#choose-a-harness-and-a-model). -The Project API key authenticates your application to this Core. It is separate from -the model provider's key that a harness uses, and neither belongs in source control. -The API base URL reaches Core directly; Web does not serve `/v1`. +## 1. Connect -## First request +Core serves the OpenAI Agents API, so the official OpenAI SDK works unchanged. It +reads two environment variables: -Use the pinned client version: +| Variable | Value | +| --- | --- | +| `OPENAI_BASE_URL` | The API base URL: the public URL plus `/v1`, such as `https://core.example/v1`. Web's **System** page shows it | +| `OPENAI_API_KEY` | Your Project API key | ```sh python3 -m venv .venv . .venv/bin/activate pip install openai==3.13.0 export OPENAI_BASE_URL=https://core.example/v1 -read -rs OPENAI_API_KEY && export OPENAI_API_KEY # paste the Project API key; it isn't echoed +read -rs OPENAI_API_KEY && export OPENAI_API_KEY # paste the key; it is not echoed ``` +Check access. This runs no model and creates no sandbox: + ```python from openai import OpenAI @@ -38,23 +44,20 @@ client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEY print(client.beta.agents.list().data) ``` -`read -rs` keeps the key out of your shell history. This read checks access; it runs no -model and creates no sandbox. The same request with curl, which keeps the key off its -command line: +An empty list means you are connected. The same check with curl: ```sh curl "$OPENAI_BASE_URL/agents" -H "OpenAI-Beta: agents=v1" \ -H @<(printf 'Authorization: Bearer %s\n' "$OPENAI_API_KEY") ``` -All keys of a Project share its assets and execution principal; other Projects are -isolated. When the administrator rotates your key, they issue a new one in the same -Project and revoke the old one; your assets stay. +## 2. Start a Session -## Run a Session +A Session is one agent conversation with its own workspace. With +`openai_hosted`, Core creates a sandbox for it on a node or E2B and starts the harness +inside. -Set the provider's exact model ID and Responses API base URL. Use a test account -that is authorized to make a model request: +With the installation's default model, skip this. To use your own provider: ```sh export MODEL_NAME='your-model-id' @@ -62,89 +65,37 @@ export MODEL_BASE_URL='https://your-provider.example/v1' read -rs MODEL_API_KEY && export MODEL_API_KEY ``` - -A Core-hosted Session (`openai_hosted`) runs in a sandbox that Core creates: on a node -with free capacity, or on E2B. Core prepares the daemon, native harness and workspace -inside it. The installation needs a ready node or an E2B backend; see -[Nodes](/hosted-providers). - ```python import os +extra = {"agent": {"x_agents_core": {"harness": "codex"}}} +if os.environ.get("MODEL_API_KEY"): + extra["agent"]["model"] = os.environ["MODEL_NAME"] + extra["x_agents_core"] = {"model_provider": { + "protocol": "responses", + "base_url": os.environ["MODEL_BASE_URL"], + "api_key": os.environ["MODEL_API_KEY"], + }} + session = client.beta.agents.sessions.create( environment={"type": "openai_hosted"}, input="Create /workspace/hello.txt with a short greeting, then describe it.", - extra_body={ - "agent": { - "model": os.environ["MODEL_NAME"], - "x_agents_core": {"harness": "codex"}, - }, - "x_agents_core": { - "model_provider": { - "protocol": "responses", - "base_url": os.environ["MODEL_BASE_URL"], - "api_key": os.environ["MODEL_API_KEY"], - } - }, - }, + extra_body=extra, ) print(session.id) ``` -This makes a real model request and may incur charges. If the administrator set a -default model for the harness, omit `x_agents_core.model_provider`; `agent.model` is -still required, so ask the administrator which model ID the default provider serves. -SDK 3.13.0 replaces an ordinary body field with the matching `extra_body` field -instead of merging nested fields, so keep the whole `agent` object in `extra_body`. - -## Core extensions: x_agents_core - -`/v1` has exactly the official routes. Core's additions are fields inside -`x_agents_core`, passed through `extra_body`; any other member is rejected with 400. - -| Field | Where | Meaning | -| --- | --- | --- | -| `x_agents_core.harness` | A saved Agent, or the Session's inline `agent` | Which native harness runs the Agent: `codex` (Codex), `claude_sdk` (Claude Code) or `mcode` (MiniMax Code). Omitted: the installation's default harness (`core.default_harness`, Codex unless changed) | -| `x_agents_core.model_provider` | A saved Agent, or Session creation | The model provider bundle: `protocol`, HTTPS `base_url`, write-only `api_key`, and for `mcode` also `context_window` and `max_output_tokens`. Reads return `api_key_configured` instead of the key | - -The provider's protocol must match the harness: +This makes a real model request and may incur charges. -| Harness | `protocol` | Also required | -| --- | --- | --- | -| Codex (`codex`) | `responses` | The provider's exact model ID in `agent.model` | -| Claude Code (`claude_sdk`) | `anthropic` | The provider's exact model ID | -| MiniMax Code (`mcode`) | `anthropic` | `context_window` and `max_output_tokens` | +- `x_agents_core` holds Core's additions to the OpenAI API; see + [Core extensions](/sessions#core-extensions-x_agents_core). +- Keep the whole `agent` object in `extra_body`. SDK 3.13.0 replaces a body field with + the matching `extra_body` field instead of merging them. -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. +## 3. Wait for the result -## Model providers - -A Session takes its model provider from the first of these that has one; bundles are -never merged: - -1. `x_agents_core.model_provider` in the Session creation request; -2. the saved Agent's `x_agents_core.model_provider`; -3. the installation's default model for the harness, set in Web on **System**, - **Default model**. - -| Environment | Request or saved Agent | Default model | None of them | -| --- | --- | --- | --- | -| `openai_hosted` | Used | Used | 400 `model_provider_required` | -| `self_hosted` | Used | Never | 400 `model_provider_required` | -| `none` | Rejected with 400 `unsupported_or_invalid_configuration` | Used | Allowed: the device's own environment supplies the model | - -A Session freezes its provider when it is created; later changes to the Agent or the -default affect only new Sessions. Core encrypts the key with the Session and never -returns it. Self-hosted Sessions always bring their own provider, because the default -holds the operator's key and the executor host belongs to the application; see -[Self-hosted executors](/self-hosted-execution). - -## Wait for the result - -Continue in the same Python process. A Session ID confirms creation, not success. -This bounded loop reads durable state instead of resubmitting work: +A Session ID confirms creation, not success. Poll durable state; never resubmit to +"retry": ```python import time @@ -155,25 +106,24 @@ for _ in range(120): turn = turns[0] print("Turn:", turn.id, turn.status) print(client.beta.agents.sessions.items.list(session.id).data) - if turn.status != "completed": - raise RuntimeError("Inspect the recorded Turn and Items before retrying") break - current = client.beta.agents.sessions.retrieve(session.id) - if current.status == "failed": + if client.beta.agents.sessions.retrieve(session.id).status == "failed": raise RuntimeError("Session preparation failed; inspect its Environment") time.sleep(1) else: - raise TimeoutError(f"Session {session.id} is still pending; inspect it before retrying") + raise TimeoutError(f"Session {session.id} is still running; inspect it before retrying") ``` -Success means the Turn is `completed` and its recorded output describes the created -file. A timeout does not cancel the task or prove failure. The -[user guide](/user-guide) explains how to inspect files, send another message, -add Skills/Plugins/MCP, cancel work and recover after disconnection. +Success is a `completed` Turn whose Items describe the new file. A timeout neither +cancels the work nor proves it failed. + +## Next steps -Files, Artifacts, cancellation and their current limits are in 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. +| To | Read | +| --- | --- | +| Stream output, send follow-up messages, upload files, add Skills or MCP, cancel | [User guide](/user-guide) | +| See every resource with request and response examples | [Agents API guide](/sessions) | +| Run the agent on your own machine | [Self-hosted execution](/self-hosted-execution) | +| See a complete application | [Examples](/examples) | [Repository source](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/docs/getting-started/quickstart.md) diff --git a/apps/docs/content/docs/self-hosted-execution.mdx b/apps/docs/content/docs/self-hosted-execution.mdx index 6a3c53f4f..4c67a7249 100644 --- a/apps/docs/content/docs/self-hosted-execution.mdx +++ b/apps/docs/content/docs/self-hosted-execution.mdx @@ -9,17 +9,15 @@ creates the Session through `/v1` and receives a command that installs and conne Linux, macOS and Windows use the same Runtime protocol. Core-managed Providers remain Linux-only. -The daemon runs with its launching user's permissions and adds no inner -filesystem, permission or network sandbox. Its tools may access that user's files -and Runtime credentials. Managed isolation belongs to the outer Environment; -self-hosted operators choose any outer isolation they need. See the -[native installation guide](/self-hosted-native) for prerequisites, commands -and supported platforms. - -An executor credential works for one Environment only. It cannot call the Agent -API, Core API or node enrollment. Default model providers never apply to -self-hosted Sessions: the request or Agent must carry its own model provider. -Otherwise creation fails with 400 `model_provider_required`. +**The daemon is not a sandbox:** tools run with its launching user's permissions. +Use a container or VM if you need isolation; see +[Runtime and outer isolation](/concepts#runtime-and-outer-isolation). +Platforms, prerequisites and commands are in the +[native Runtime guide](/self-hosted-native). + +An executor credential works for one Environment only, and for nothing else. The +Session must bring its own model provider; the installation default never applies +([why](/user-guide#which-model-provider-a-session-uses)). ## Connect a host @@ -53,6 +51,8 @@ Otherwise creation fails with 400 `model_provider_required`. installation directory when prompted. Installation creates the workspace if needed, starts the daemon and checks its connection. For automation, append `--non-interactive --harness codex` and optionally `--install-dir ABS`. +3. Send a Turn. A connected Environment proves only the machine connection; the + first Turn checks the harness and model. In Web, open the **Self-hosted** Session and copy the command under **Connect a host**. A command expires after 30 minutes; fetch the Session again for a fresh @@ -60,10 +60,6 @@ one. The [native guide](/self-hosted-native#install-and-connect) covers retry, platform prerequisites and credential storage. Core must be reachable from the host with TLS outside loopback. Native installation does not require Docker. -A connected Environment proves only the machine connection. Send a Turn to check -the selected harness and model. Core supplies the Session's model provider over -this Environment's authenticated executor connection. The host's user and tools -running with that user's permissions can access locally stored Runtime data. ## Local capability directories diff --git a/apps/docs/content/docs/self-hosted-native.mdx b/apps/docs/content/docs/self-hosted-native.mdx index 92342f6db..715d4cb6d 100644 --- a/apps/docs/content/docs/self-hosted-native.mdx +++ b/apps/docs/content/docs/self-hosted-native.mdx @@ -8,13 +8,10 @@ Physical machines, VMs and user-owned sandboxes use the same installer. Core doe not create or reclaim these machines. Core-managed Docker, E2B and microsandbox Providers remain Linux-only and receive prebuilt Runtime images or templates. -The daemon runs with its starting account's permissions, without an inner sandbox -or privilege elevation. Tools can access whatever that account can access. Use an -outer container or VM when isolation is required. Connection authentication, -Project/Environment authorization, credential permissions, Files path validation, -process cleanup and snapshot consistency still apply; they do not isolate tools -from their own account. `disabled` and `restricted` network modes require an outer -implementation that enforces them. +**The daemon is not a sandbox.** Tools can access whatever its account can. Use an +outer container or VM when you need isolation; see +[Runtime and outer isolation](/concepts#runtime-and-outer-isolation). +`disabled` and `restricted` network modes need an outer layer that enforces them. ## Platforms and prerequisites @@ -131,11 +128,9 @@ Harness while the daemon is running, restart it to refresh Harness discovery. `status` reports local profile/PID-file information only. Check **Host connection** in Core or the Environment connection API for authenticated connection state. -A connected Environment proves machine authentication, not model availability. -Configure the model provider through the existing Session/Agent mechanism and -send a Turn to verify execution. Rotate a credential by stopping the daemon, -replacing the JSON at the configured path with the rotated credential for the -same `key_id`, and starting again. Revocation blocks the old credential. +A connected Environment proves machine authentication, not model availability: +send a Turn to verify execution. To rotate or revoke the credential, see +[Rotate or revoke](/self-hosted-execution#rotate-or-revoke). An incompatible daemon version, component version or modified installation is an explicit error. Use a separate installation directory; there is no old-version diff --git a/apps/docs/content/docs/sessions.mdx b/apps/docs/content/docs/sessions.mdx index 577f29465..cdf6b45f7 100644 --- a/apps/docs/content/docs/sessions.mdx +++ b/apps/docs/content/docs/sessions.mdx @@ -1,100 +1,574 @@ --- -title: "Sessions and public resources" -description: "Agents, Sessions, Turns, events and resources in the pinned public contract." +title: "Agents API guide" +description: "Every public resource with OpenAI SDK and HTTP examples: Agents, Sessions, input, streaming, files, Skills, templates and Vaults." --- -Applications call Core directly with an API key issued inside a Project. They use -the public API to create and execute Agents, query history, and manage their assets. -They never use the Core key or the console's browser session cookie. +Core serves the [OpenAI Agents API](https://platform.openai.com/docs/api-reference) at +`/v1`. Use the official OpenAI SDK or plain HTTP. This guide shows both for every +common operation, and notes where Core differs from OpenAI. -## Authentication and base URL +New to the API? Run the [quickstart](/quickstart) first. -Set `OPENAI_BASE_URL` to the installation's API base URL (`api_base_url` in -`GET /core/v1/installation`: the public URL followed by `/v1`) and `OPENAI_API_KEY` -to a Project API key; the official SDK reads both. Raw HTTP callers send -`Authorization: Bearer `. The fixed SDK supplies -`OpenAI-Beta: agents=v1` for the Beta Agents resources; raw HTTP callers must add -it. General Files and Skills endpoints do not require that Beta header. +## Before you start + +**Base URL and key.** Your administrator gives you the API base URL, such as +`https://core.example/v1`, and a Project API key. + +```sh +export OPENAI_BASE_URL=https://core.example/v1 +read -rs OPENAI_API_KEY && export OPENAI_API_KEY +``` + +**SDK.** Use the pinned version: + +```sh +pip install openai==3.13.0 +``` ```python from openai import OpenAI -client = OpenAI() # Reads OPENAI_API_KEY and OPENAI_BASE_URL. -page = client.beta.agents.list() +client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEY +``` + +**HTTP.** Every request needs a Bearer key. Routes under `/agents` and `/vaults` also +need `OpenAI-Beta: agents=v1`; `/files` and `/skills` do not. The SDK sets both. The +HTTP examples below use this shell helper: + +```sh +oac() { # oac PATH [curl options]: call /agents or /vaults with the required headers + curl -sS "$OPENAI_BASE_URL$1" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: agents=v1" \ + -H "Content-Type: application/json" "${@:2}" +} +oac /agents +``` + +On a shared host, `-H @<(printf 'Authorization: Bearer %s\n' "$OPENAI_API_KEY")` +keeps the key out of the process list. + +## Resources at a glance + +| Resource | Path | What it is | +| --- | --- | --- | +| [Agents](#agents) | `/agents` | Reusable configuration: model, instructions, tools, harness | +| [Sessions](#sessions) | `/agents/sessions` | One agent conversation with its own Environment | +| [Input events](#send-input) | `/agents/sessions/{id}/events` (POST) | Messages, cancellation and tool results | +| [Event stream](#stream-events) | `/agents/sessions/{id}/events` (GET) | Live server-sent events | +| [Turns and Items](#turns-and-items) | `/agents/sessions/{id}/turns`, `/items` | Durable history | +| [Files](#files) | `/files`, `/agents/environments/{id}/files`, `/agents/sessions/{id}/artifacts` | Uploads, workspace files and outputs | +| [Skills](#skills) | `/skills` | Versioned capability bundles | +| [Environment Templates](#environment-templates) | `/agents/environments/templates` | Reusable workspace setup | +| [Vaults](#vaults) | `/vaults` | Write-only credentials for MCP servers | +| Subagents | `/agents/sessions/{id}/subagents` | Read-only child work; see [subagents](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/subagents.md) | + +Core has exactly the routes of the pinned SDK, listed in +[upstream-routes.json](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/upstream-routes.json). It adds no +route; its additions live in [`x_agents_core`](#core-extensions-x_agents_core). + +## Conventions + +### Pagination + +Lists return: + +```json +{"object": "list", "data": [...], "has_more": true, "first_id": "...", "last_id": "..."} +``` + +| Parameter | Meaning | +| --- | --- | +| `limit` | 1–100, default 20 | +| `order` | `desc` (default) or `asc` | +| `after` | Pass the previous page's `last_id` | + +The SDK pages for you: + +```python +for session in client.beta.agents.sessions.list(limit=100): + print(session.id, session.status) +``` + +```sh +oac "/agents/sessions?limit=100&after=$LAST_ID" +``` + +Two lists differ: `GET /files` returns up to 10,000 files at once, and workspace +files use an opaque `page` token (see [Workspace files](#workspace-files)). + +### Idempotency + +Send an `Idempotency-Key` (up to 128 bytes) when creating a Session or sending input. +A retry with the same key and body returns the original result instead of doing the +work twice. The same key with a different body fails with 409 `idempotency_conflict`. + +```python +import uuid + +key = str(uuid.uuid4()) # store it before sending, reuse it on retry +client.beta.agents.sessions.events.create(session_id, events=[...], idempotency_key=key) +client.beta.agents.sessions.create(environment=..., extra_headers={"Idempotency-Key": key}) +``` + +**After a lost response,** retry with the same key, then read the Session, Turns and +Items. Never resend without the key. Core keeps creation keys even after the Session +is deleted. + +> Core difference: OpenAI creates a new Session for each create request even with the +> same key. Core returns the original. + +### Errors + +```json +{"error": {"type": "invalid_request_error", "message": "...", "code": "model_provider_required", "param": "x_agents_core.model_provider"}} +``` + +| Status | Common codes | Meaning | +| --- | --- | --- | +| 400 | `invalid_request_error`, `invalid_beta`, `model_provider_required`, `unsupported_or_invalid_configuration` | Fix the request. `invalid_beta` means a missing or wrong `OpenAI-Beta` header | +| 401 | `invalid_api_key` or none | Wrong or missing key, or a key from another namespace | +| 404 | | Missing, or belongs to another Project. The two look the same | +| 405 | `unsupported_operation` | Core doesn't support this operation | +| 409 | `conflict_error`, `idempotency_conflict` | State conflict, for example deleting a busy Session | +| 413 | | Body too large | +| 503 | | Temporarily uncertain; read state before retrying | + +Every response carries `X-Request-Id`; include it when reporting a problem. + +### Core extensions: `x_agents_core` + +Core runs several harnesses and accepts your own model access. Those settings are the +only additions to the OpenAI shapes, and they sit inside `x_agents_core`: + +| Field | Where | Value | +| --- | --- | --- | +| `harness` | Agent, or a Session's inline `agent` | `codex`, `claude_sdk` or `mcode` | +| `model_provider` | Agent, or Session creation (top level) | `protocol` (`responses`, `anthropic` or `chat_completions`), `base_url`, `api_key`, and for `mcode` also `context_window` and `max_output_tokens` | +| `harness_config` | Agent, inline `agent`, or Session creation (top level, wins) | The harness's native model parameters, such as Codex's `model_reasoning_effort` | +| `installation` | Read-only, on `self_hosted` Sessions | Short-lived install commands for your machine; see [self-hosted execution](/self-hosted-execution) | + +Any other member is rejected with 400. `api_key` is write-only: reads return +`api_key_configured`. `harness_config` replaces the whole object; `{}` clears it. With the SDK, pass these through `extra_body`. How to pick a +harness and model, and which provider a Session uses, is in the +[user guide](/user-guide#choose-a-harness-and-a-model). + +## Agents + +An Agent is saved configuration. Sessions copy it when they start, so editing an +Agent affects only new Sessions. + +```python +agent = client.beta.agents.create( + model="your-model-id", + name="Reviewer", + instructions="Review code changes and report problems.", + extra_body={"x_agents_core": {"harness": "codex"}}, +) +``` + +```sh +oac "/agents" -d '{ + "model": "your-model-id", + "name": "Reviewer", + "instructions": "Review code changes and report problems.", + "x_agents_core": {"harness": "codex"} +}' +``` + +```json +{"id": "agent_...", "object": "agent", "model": "your-model-id", "name": "Reviewer", + "instructions": "...", "tools": [], "metadata": {}, "created_at": 1790000000, + "x_agents_core": {"harness": "codex"}} ``` -This read does not execute a model. See the [real execution quickstart](/quickstart) -for separate model access configuration and a complete Session example. +| Operation | SDK | HTTP | +| --- | --- | --- | +| Create | `agents.create(...)` | `POST /agents` | +| Read | `agents.retrieve(id)` | `GET /agents/{id}` | +| Update | `agents.update(id, ...)` | `POST /agents/{id}` | +| List | `agents.list()` | `GET /agents` | +| Delete | `agents.delete(id)` | `DELETE /agents/{id}` | + +(`agents` is `client.beta.agents` throughout.) + +- **Update** changes only the fields you send. `metadata` replaces all pairs; `null` + clears `name` or `instructions`. +- **Delete** keeps existing Sessions. +- **Tools** are functions, MCP servers, `tool_search` (Claude) and `web_search` with + `mode: "disabled"`. Support depends on harness and Environment; see + [execution tools](/agents-and-tools). + +## Sessions + +A Session is one conversation with a fixed configuration and its own Environment. + +### Create a Session + +```python +session = client.beta.agents.sessions.create( + environment={"type": "openai_hosted"}, + agent_id=agent.id, + input="Review the files in /workspace and summarize the risks.", + metadata={"ticket": "T-123"}, +) +``` + +```sh +oac "/agents/sessions" -H "Idempotency-Key: $(uuidgen)" -d '{ + "environment": {"type": "openai_hosted"}, + "agent_id": "agent_...", + "input": "Review the files in /workspace and summarize the risks.", + "metadata": {"ticket": "T-123"} +}' +``` -All keys in a Project share assets and Session creator identity. Revoking one key -leaves the others valid; archiving the Project revokes all its keys. The optional -`OpenAI-Organization` and `OpenAI-Project` headers must match `core` and -`proj_` respectively. Do not send a key's UUID as the project scope. +Returns 201 with the Session: -## Public resources +```json +{"id": "sess_...", "object": "agent.session", "status": "in_progress", + "agent": {"model": "...", ...}, "environment": {"id": "env_...", "type": "openai_hosted", ...}, + "metadata": {"ticket": "T-123"}, "required_actions": [], "vault_ids": [], + "created_at": 1790000000, "last_active_at": 1790000000} +``` -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/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. +| Field | Meaning | +| --- | --- | +| `environment` | Required. Where the agent works; see the table below | +| `agent_id` or `agent` | A saved Agent, or an inline Agent object (same fields as create). An inline Agent on `openai_hosted` or `none` may omit `model` to use the installation default | +| `input` | The first message: a string or a message array. Optional for `openai_hosted` and `self_hosted` | +| `metadata` | Your own string key-value pairs | +| `vault_ids` | [Vaults](#vaults) whose credentials MCP servers may use | +| `stream` | `true` returns [server-sent events](#stream-events) instead of JSON | +| `x_agents_core.model_provider` | This Session's model access, if not from the Agent or the default | -| Resource | Route family | Semantics | +| `environment.type` | Runs on | Notes | | --- | --- | --- | -| Agents | `/agents` | Reusable configuration, CRUD and lists | -| 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/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, -Turns and Items to reconcile state. An accepted request is not proof of completed -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/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 | +| `openai_hosted` | A sandbox Core creates (node or E2B) | Optional `network`, `packages`, `files`, `skills`, `plugins`, `setup_commands`, or a template | +| `self_hosted` | Your machine | Requires an absolute `workspace_directory`. The response carries install commands in `x_agents_core.installation`; see [self-hosted execution](/self-hosted-execution) | +| `none` | An existing device connection | `input` required; uses the default model only | + +### Session status + +| `status` | Meaning | +| --- | --- | +| `in_progress` | A Turn is running | +| `idle` | Waiting for input | +| `requires_action` | Waiting for you: a [function result](#function-tools) or a self-hosted machine to connect | +| `failed` | The Environment could not be prepared. See `error` | + +### Update, list and delete + +```python +client.beta.agents.sessions.update(session.id, metadata={"ticket": "T-124"}) +for s in client.beta.agents.sessions.list(agent_id=agent.id): + print(s.id) +client.beta.agents.sessions.delete(session.id) +``` + +| Operation | HTTP | Notes | | --- | --- | --- | -| `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 -`/core/v1`, which only the Core key can call (see the [API index](/public-api)). - -A Session's model provider comes from the Session's `x_agents_core.model_provider`, -then a saved Agent's, then the deployment default that the administrator sets per -harness. The deployment default applies to `openai_hosted` and `none` Sessions, -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/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 -default harness omits `agent.x_agents_core`. `/v1` has no execution-configuration -read. - -`openai_hosted` keeps the official wire name and means Core-managed compute here. -The deployment chooses E2B or its own Docker/microsandbox nodes. A public -`self_hosted` Environment uses caller-owned compute and the same colocated -Runtime on Linux, macOS or Windows; managed Providers remain Linux-only. Native -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/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. +| Read | `GET /agents/sessions/{id}` | | +| Update | `POST /agents/sessions/{id}` | Only `metadata` | +| List | `GET /agents/sessions?agent_id=...` | Filter by Agent is optional | +| Delete | `DELETE /agents/sessions/{id}` | Only when `idle` or `failed` with nothing pending; otherwise 409. Cancel first | + +## Send input + +All input goes to one endpoint as a list of events. It returns 202 once the input is +stored, before the agent reads it. + +### Send a message + +```python +client.beta.agents.sessions.events.create( + session.id, + events=[{ + "type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Now fix the first risk."}]}], + }], + idempotency_key=key, +) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -H "Idempotency-Key: $KEY" -d '{ + "events": [{"type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Now fix the first risk."}]}]}] +}' +``` + +- **When idle,** a message starts a new Turn. **While a Turn runs,** it joins that + Turn (steering); it does not start a parallel task. +- **Content** is `input_text`, plus `input_image` as an inline PNG or JPEG data URI. + Images work with Codex and Claude Code, on `none` and Docker sandboxes only. The + whole request is limited to 1 MiB. +- Full rules: [message input](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md). + +### Cancel + +```python +client.beta.agents.sessions.events.create(session.id, events=[{"type": "agent.session.input.cancel"}]) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -d '{"events": [{"type": "agent.session.input.cancel"}]}' +``` + +The Turn is cancelled when it reaches `cancelled`, not when the request returns. A +cancel while idle does nothing. + +## Stream events + +`GET /agents/sessions/{id}/events` is a server-sent event stream. It is **live only**: +events sent while you were disconnected are not replayed. Open it before sending +input, and recover gaps from [Turns and Items](#turns-and-items). + +```python +with client.beta.agents.sessions.events.stream(session.id) as stream: + for event in stream: + if event.type == "agent.session.turn.output_text.delta": + print(event.delta, end="", flush=True) + elif event.type in {"agent.session.turn.completed", "agent.session.turn.failed", "agent.session.turn.cancelled"}: + break +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -N +``` + +```text +event: agent.session.turn.output_text.delta +data: {"type": "agent.session.turn.output_text.delta", "item_id": "item_...", "delta": "Hello", ...} +``` + +| Event | When | +| --- | --- | +| `agent.session.turn.created`, `.in_progress` | A Turn starts | +| `agent.session.turn.item.added`, `.item.done` | An Item (message, tool call, …) starts or finishes | +| `agent.session.turn.output_text.delta`, `.done` | Assistant text, piece by piece | +| `agent.session.turn.completed`, `.failed`, `.cancelled` | A Turn ends. Carries `usage` | +| `agent.session.in_progress`, `.idle`, `.requires_action`, `.failed` | Session status changes | +| `agent.session.subagent.*` | Child work starts or ends | +| `error` | A stream-level error | + +The stream stays open across Turns. To stream one Turn and handle +[function calls](#function-tools) automatically, the SDK's `sessions.stream` helper +does both. + +**Stream the creation itself** with `stream=True` on `sessions.create`. You get +`agent.session.created` first, and the stream ends at the first `idle` or `failed`. + +**Reconnecting:** resubscribe, then read Items and drop any you already have by ID. +Details: [history and events](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/history-events-usage.md). + +## Turns and Items + +A Turn is one piece of work started by input. Items are its recorded content: +messages, reasoning, tool calls and their results. Both are durable; read them to +check results or recover after a disconnect. + +```python +turns = client.beta.agents.sessions.turns.list(session.id, order="desc") +latest = turns.data[0] +print(latest.status, latest.usage) +for item in client.beta.agents.sessions.items.list(session.id, order="asc"): + print(item.type) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/turns?order=desc&limit=1" +oac "/agents/sessions/$SESSION_ID/items?order=asc" +``` + +| Turn `status` | Meaning | +| --- | --- | +| `queued`, `in_progress` | Not finished | +| `waiting` | Waiting for a function result | +| `completed`, `failed`, `cancelled` | Finished | + +- **Usage** (`input_tokens`, `output_tokens`, `total_tokens`, …) may arrive after the + Turn ends. Treat `null` as "not yet known", not zero. +- Turn lists contain top-level Turns only. Read child work under `/subagents`. + +## Function tools + +Declare a function on the Agent. When the model calls it, the Session enters +`requires_action` and the Turn `waiting` until you return a result. + +```python +agent = client.beta.agents.create( + model="your-model-id", + tools=[{ + "type": "function", + "name": "get_weather", + "description": "Current weather for a city", + "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}, + }], +) + +def get_weather(args): + return f"Sunny in {args['city']}" + +with client.beta.agents.sessions.stream( + session.id, input="What's the weather in Paris?", tool_handlers={"get_weather": get_weather} +) as stream: + for event in stream: + pass # the helper submits each result and stops when the Turn ends +``` + +Without the helper, read the call from `session.required_actions`, then send: + +```sh +oac "/agents/sessions/$SESSION_ID/events" -d '{ + "events": [{"type": "agent.session.input.tool_result", + "turn_id": "turn_...", "call_id": "call_...", "success": true, "output": "Sunny in Paris"}] +}' +``` + +Resending the same result is safe. A different result for the same call, or one sent +after cancellation, fails with 409. MiniMax Code doesn't support public functions. + +## Files + +Three kinds of file serve different purposes: + +| Kind | Use it to | Path | +| --- | --- | --- | +| [Source Files](#source-files) | Upload bytes once and reference them by ID | `/files` | +| [Workspace files](#workspace-files) | Put files into a running Session's workspace, or list it | `/agents/environments/{id}/files` | +| [Artifacts](#artifacts) | Download what the agent produced | `/agents/sessions/{id}/artifacts` | + +### Source Files + +```python +f = client.files.create(file=open("data.csv", "rb"), purpose="user_data") +``` + +```sh +curl "$OPENAI_BASE_URL/files" -H "Authorization: Bearer $OPENAI_API_KEY" \ + -F purpose=user_data -F file=@data.csv +``` + +Only `purpose=user_data` is accepted, up to 512 MiB. No Beta header. Their content +cannot be downloaded again; use the ID in workspace files or templates. + +### Workspace files + +Copy a file into the workspace of the Session's Environment (`session.environment.id`): + +```python +env_id = session.environment.id +client.beta.agents.environments.files.create(env_id, type="file_id", file_id=f.id, path="/workspace/data.csv") +client.beta.agents.environments.files.create(env_id, type="inline", data="aGVsbG8K", path="/workspace/hello.txt") +page = client.beta.agents.environments.files.list(env_id, path="/workspace") +``` + +```sh +oac "/agents/environments/$ENV_ID/files" -d '{"type": "file_id", "file_id": "file_...", "path": "/workspace/data.csv"}' +``` + +- `inline` data is base64, up to 5 MiB decoded; `file_id` up to 50 MiB. +- Parent directories are created. An existing file is never overwritten (400). +- The list shows regular files in one directory, not recursively. It pages with a + `page` token and returns `next`. + +### Artifacts + +When a Turn completes, Core captures the regular files under the workspace's +`outputs/` directory. Artifacts stay readable after the Environment is gone. + +```python +for a in client.beta.agents.sessions.artifacts.list(session.id): + data = client.beta.agents.sessions.artifacts.content(a.id, session_id=session.id) + data.write_to_file(a.path.rsplit("/", 1)[-1]) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/artifacts" +oac "/agents/sessions/$SESSION_ID/artifacts/$ARTIFACT_ID/content" -o report.md +``` + +Each Artifact has `path`, `size_bytes`, `turn_id` and `environment_id`. Deleting one +leaves the workspace file alone. + +## Skills + +A Skill is a versioned bundle of instructions and files an agent can use. Upload a +directory or a ZIP; each upload is a version. + +```sh +curl "$OPENAI_BASE_URL/skills" -H "Authorization: Bearer $OPENAI_API_KEY" -F files=@my-skill.zip +``` + +```python +skill = client.skills.create(files=[("my-skill/SKILL.md", open("my-skill/SKILL.md", "rb"))]) +client.skills.versions.create(skill.id, files=[...], default=True) +``` + +- No Beta header. Up to 50 Skills; 5 MiB compressed, 20 MiB expanded per archive. +- SDK 3.13.0 drops a single ZIP file from the upload; use HTTP for a ZIP. +- Attach Skills to a Session through its `environment.skills` or a + [template](#environment-templates). + +Details: [Source Files and Skills](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/source-files.md). + +## Environment Templates + +A template saves workspace setup for reuse by `openai_hosted` Sessions: + +```python +template = client.beta.agents.environments.templates.create( + name="python-data", + network={"access": "restricted", "allowed_domains": ["pypi.org", "files.pythonhosted.org"]}, + packages={"python": ["pandas"]}, + setup_commands=["mkdir -p /workspace/outputs"], +) +``` + +| Field | Meaning | +| --- | --- | +| `network` | `access`: `enabled`, `disabled`, or `restricted` to 1–100 exact hosts in `allowed_domains`. A Session can only narrow it | +| `packages` | `npm` and `python` packages. `system` packages are rejected: bake them into the image | +| `setup_commands`, `env` | Run and set at preparation. Never returned by reads | +| `files`, `skills`, `plugins` | Initial content. Up to 50 files, 10 MiB inline in total | + +A Session freezes the template when it starts. Details: +[Environment Templates](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/environment-templates.md). + +## Vaults + +Vaults hold credentials for HTTP MCP servers: a `static_bearer` token or an `mcp_oauth` +token with optional refresh. Tokens are write-only. + +```python +vault = client.beta.agents.vaults.create(name="github") +client.beta.agents.vaults.credentials.create( + vault.id, name="github-token", + auth={"type": "static_bearer", "token": "ghp_...", "mcp_server_url": "https://api.githubcopilot.com/mcp/"}, +) +session = client.beta.agents.sessions.create(environment={"type": "none"}, input="...", vault_ids=[vault.id], agent_id=agent.id) +``` + +The HTTP path is `/vaults`, with the Beta header. A credential is used when an MCP +server's URL matches its `mcp_server_url` exactly, or when the tool names its +`credential_id`. Service-origin MCP works with Codex and Claude Code on `none` +Sessions only. + +## Limits and differences from OpenAI + +| Area | Core behavior | +| --- | --- | +| Routes | Exactly the pinned SDK's routes; no extra routes | +| Extensions | Only `x_agents_core.harness` and `x_agents_core.model_provider` | +| Session create idempotency | Same key returns the original Session | +| Event stream | Live only; no replay, `Last-Event-ID` ignored | +| Tools | No enabled `web_search`; no multi-agent with functions; MiniMax Code has no public functions | +| Images | Inline PNG/JPEG only; Codex and Claude Code; `none` and Docker sandboxes | +| Packages | `packages.system` rejected | + +Per-operation status and harness differences are in the +[coverage record](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/README.md). The exact schemas are in the +[public OpenAPI](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/openapi.yaml). [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 0aaf69af8..8b664c7ce 100644 --- a/apps/docs/content/docs/troubleshooting.mdx +++ b/apps/docs/content/docs/troubleshooting.mdx @@ -122,15 +122,17 @@ 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/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. - -To rotate an application key, issue another key in the same Project, update the -application, then **Revoke** the old key. **Archive** disables all of a Project's keys -and keeps its assets and accepted work. Administrators can inspect and delete retained -resources but can't execute with the Core key. +Create Projects and issue keys in Web, on **Projects and keys**, or through the +[Core API](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/admin-api.md) under `/core/v1/projects`. How +Projects and keys behave is in [Projects own assets](/concepts#projects-own-assets). + +To rotate an application key: + +1. Issue a new key in the same Project. +2. Update the application to use it. +3. **Revoke** the old key. + +**Archive** disables every key of a Project and keeps its assets. ## Data and current-release repair diff --git a/apps/docs/content/docs/user-guide.mdx b/apps/docs/content/docs/user-guide.mdx index 0401114ba..a23ba170b 100644 --- a/apps/docs/content/docs/user-guide.mdx +++ b/apps/docs/content/docs/user-guide.mdx @@ -3,118 +3,159 @@ title: "Use OpenAgentCore" description: "Sessions, capabilities, files, cancellation and recovery." --- -Complete the [first Session walkthrough](/quickstart) before using -this guide. It provides `client` and `session`; the examples below continue that -Session. For exact request fields, use the [API reference](/public-api). +Common tasks for application developers. Start with the +[quickstart](/quickstart); it sets up `client` and `session`. Every +operation here is shown with SDK and HTTP examples in the +[Agents API guide](/sessions). ## Choose where a task runs -| Environment | What you prepare | Next step | +A Session's `environment.type` decides where its agent works: + +| Environment | Runs on | You prepare | | --- | --- | --- | -| `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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-selection.md) | +| `openai_hosted` | A sandbox Core creates on a node or E2B | Nothing; the administrator provides capacity | +| `self_hosted` | Your own Linux, macOS or Windows machine | The machine, a workspace directory and the daemon. See [self-hosted execution](/self-hosted-execution) | +| `none` | An existing device connection, no workspace | A connected device with its harness | + +Placement, expiry and supported combinations: +[Environment contract](/environments-and-files). + +## Choose a harness and a model + +The harness is the agent program that runs your Session. Set it in +`x_agents_core.harness` on the Agent; if you don't, the installation's default +(Codex unless changed) is used. + +| Harness | `harness` | Native model parameters (`harness_config`) | +| --- | --- | --- | +| Codex | `codex` | `model_reasoning_effort` | +| Claude Code | `claude_sdk` | `effort`, `thinking` | +| MiniMax Code | `mcode` | None. The provider must set `context_window` and `max_output_tokens` | + +- **Model.** `agent.model` is the provider's exact model ID. An inline Agent on an + `openai_hosted` or `none` Session may omit it to use the installation default's + model. Saved Agents always need one. +- **Provider protocol.** Any harness accepts `responses`, `anthropic` or + `chat_completions`; the Runtime converts when the harness doesn't speak it + natively. Native model parameters need a native protocol. +- **Native parameters.** `x_agents_core.harness_config` passes the harness's own + settings; see [native model configuration](/harness-onboarding#native-model-configuration). -Use the [Environment contract](/environments-and-files) for placement, -expiry and supported combinations. Model selection and provider precedence are -explained once in the [application quickstart](/quickstart#model-providers). +Selecting a harness doesn't make an unsupported model or operation work; see +[harness selection](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/harness-selection.md). -## Continue a Session +### Which model provider a Session uses -A Session keeps the conversation and its fixed execution configuration. Submit a -follow-up after the previous Turn settles: +A Session takes its model provider from the first of these that has one. They are +never merged: + +1. `x_agents_core.model_provider` in the Session creation request; +2. the saved Agent's `x_agents_core.model_provider`; +3. the installation's default model configuration for the harness, set by the + administrator. It also supplies the model and native parameters when the Session + leaves them out. + +| Environment | Request or Agent provider | Installation default | Neither | +| --- | --- | --- | --- | +| `openai_hosted` | Used | Used | 400 `model_provider_required` | +| `self_hosted` | Used | Never | 400 `model_provider_required` | +| `none` | Rejected (400) | Used | Allowed: the device supplies the model | + +Self-hosted Sessions never use the default, because it holds the operator's key and +your machine is outside the operator's control. A Session freezes its provider at +creation; later changes affect only new Sessions. Full rules: +[model execution](https://github.com/MiniMax-AI/parsar-core/blob/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/model-execution.md). + +## Follow up and steer + +Send another message to the same Session to continue with its history and workspace: ```python -client.beta.agents.sessions.events.create( - session.id, - events=[{ - "type": "agent.session.input.message", - "input": [{ - "role": "user", - "content": [{"type": "input_text", "text": "Summarize the file you created."}], - }], - }], -) +client.beta.agents.sessions.events.create(session.id, events=[{ + "type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Summarize the file you created."}]}], +}]) ``` -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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/message-input.md) -for supported content, steering and idempotency rules. +- **Idle Session:** the message starts a new Turn. +- **Running Turn:** the message joins it (steering). It never starts a parallel task. +- **Different configuration or workspace:** create a new Session. + +See [Send input](/sessions#send-input). -## Prepare Skills, Plugins and MCP +## Watch the output live -Select capabilities when creating the Session, before sending work that needs them. -Runtime installs one snapshot and passes its Skill paths and MCP declarations to the -Harness. Reconnect reuses that snapshot; changing local source files does not alter -an existing Session. +Open the event stream before sending input, and print text as it arrives: -| Task | Guide | +```python +with client.beta.agents.sessions.events.stream(session.id) as stream: + for event in stream: + if event.type == "agent.session.turn.output_text.delta": + print(event.delta, end="", flush=True) + if event.type in {"agent.session.turn.completed", "agent.session.turn.failed", "agent.session.turn.cancelled"}: + break +``` + +The stream is live only. After a disconnect, read Turns and Items to fill the gap. +See [Stream events](/sessions#stream-events). + +## Give the agent Skills, Plugins and MCP + +Choose capabilities when you create the Session. The Runtime installs them once, as a +snapshot; editing the source later doesn't change a running Session. + +| To | Use | | --- | --- | -| 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/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/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 -platform support. Missing preparation fails before execution; do not retry a task -as a new Session to work around an unresolved preparation error. - -## Read results and files - -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/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/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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/source-files.md) | +| Upload a Skill and pick a version | [Skills](/sessions#skills) | +| Reuse packages, files, setup and network rules | [Environment Templates](/sessions#environment-templates) | +| Call your own code from the agent | [Function tools](/sessions#function-tools) | +| Connect an MCP server, with credentials | [Execution tools](/agents-and-tools) and [Vaults](/sessions#vaults) | +| Use Skill or Plugin directories on your machine | [Local capability directories](/self-hosted-execution#local-capability-directories) | + +System packages must already be in the machine or image. Preparation errors fail the +Session before any work runs; fix the cause instead of retrying in a new Session. -These resources have different lifetimes. Deleting a Session does not erase files -from a user-owned machine. Reclaiming managed compute is a separate Environment -operation; stopping an executor does not imply reclamation. +## Send files and get results + +| To | Use | +| --- | --- | +| Put a file in the workspace | [Workspace files](/sessions#workspace-files) | +| Upload once, reference by ID | [Source Files](/sessions#source-files) | +| Download what the agent wrote to `outputs/` | [Artifacts](/sessions#artifacts) | +| Read the conversation and tool results | [Turns and Items](/sessions#turns-and-items) | + +Deleting a Session doesn't erase files on your own machine. Reclaiming a managed +sandbox is a separate operation. ## Cancel and recover -To cancel current work: +Cancel the current Turn: ```python -client.beta.agents.sessions.events.create( - session.id, - events=[{"type": "agent.session.input.cancel"}], -) +client.beta.agents.sessions.events.create(session.id, events=[{"type": "agent.session.input.cancel"}]) ``` -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/f45a4198aca79bf252412c55cad3647f5d704515/contracts/agents-api/core-errors.md). +The work has stopped when the Turn reads `cancelled`, not when the request returns. -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 -execution, restart the same installation with its retained workspace and native -history; follow the [operator lifecycle](/self-hosted-native#add-harnesses-and-operate-the-installation). -A new Session captures a new configuration, not the history of a deleted one. +After a lost response or connection: + +1. Read the Session, its Turns and Items. +2. If the work isn't there, retry with the **same** `Idempotency-Key`. +3. Never resend without a key; you may run the work twice. + +On a self-hosted machine, restart the same installation to keep its workspace and +history; see [operating the installation](/self-hosted-native#add-harnesses-and-operate-the-installation). ## Diagnose a failure -1. Check the Session, latest Turn and required actions in the API or Web. -2. Confirm that the Environment is connected and its selected Harness is available. -3. Check the model/provider and capability combination against - [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/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. +1. Read the Session's `status` and `error`, and the latest Turn's `error`. +2. Check that the Environment is connected and its harness is available. +3. Check the harness, model and tool combination in + [execution tools](/agents-and-tools). +4. Ask the administrator to check [operations and troubleshooting](/troubleshooting#troubleshooting) + for service logs, credentials and node readiness. + +A 401 usually means a key from the wrong namespace; see the [API index](/public-api). [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 e40a09c45..50476d35d 100644 --- a/apps/docs/content/guide-sources.json +++ b/apps/docs/content/guide-sources.json @@ -1,55 +1,57 @@ { "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/README.md": "d46e1b6cd0693a282f504297c87df6ddf26b99ce8c7afdb613666acd836767f5", + "docs/design-principles.md": "21a05fb089804db6fab5674ec9a6cf849a3affedad2ca927a38d9b46eeec9a50", + "docs/web/architecture.md": "b00352d49295a8ac4440420b748421af81a90778531698c707fefff4eb6223b1", + "docs/getting-started/install.md": "30c12edfdfb40c136065d0a83aad28568d7041328cc5d480d0546847d1b72e7d", "docs/getting-started/install-options.md": "c806f8f229edccc8bcc4a853976e330cfee6025c9d3d00f6960fe2ee97a8c1d6", - "docs/configuration.md": "77e24331a51f0053e968f8b18daee7d0517ec635842e0b01fca4d93c0a26d734", - "docs/web/core-connection.md": "46f86520e70bf41079708e2c398655aa9087ad9488c8e661d9a73035d11098c4", - "docs/getting-started/quickstart.md": "238b4de1137edb8c2998b38f4525fea345a19fd4de7a455aa9c4c9e4fc3c9b36", - "docs/api/README.md": "e9af18bf54c0625ab63a01d2cba4337ece555d570bddc6471767e406501a5bc1", + "docs/configuration.md": "6f1bda6a9d16f893a14dcca6fe7df0b93acba77654a23248dee3b0f0ec288a24", + "docs/web/core-connection.md": "6467595fde1c8931f27de76ac38762dfb5a7880651e859d9aa71e233ea95a9c1", + "docs/getting-started/quickstart.md": "963e39eb81c65511a28d0826b2d8c3849dc29d1b810de12df2859d7aefd6d266", + "docs/api/README.md": "5e0b3ae0e178673f2727b74a55ce566fd562006cc5e9a8a7929ea6a183cef154", "contracts/agents-api/execution-tools.md": "e0b61f6c0c236c362186c5f6d0ad69a16dd8a8d9afabe1329a1fe22e5f4a71e9", - "docs/api/public-agent-api.md": "5b04e5ec9311df851376f66fc1584dd48ca123cd8c26ca63277c10b9172e9955", + "docs/api/public-agent-api.md": "219efab820d8b5cd35855d105b7cfc2b45c7e703f04a0145bf435a99b08a9e38", + "docs/examples.md": "0e1bdaeff51c9c36779f817be31ea9816b7d8cb2290cf8350d3c4801f436f4f9", "contracts/agents-api/environments.md": "4c4b9423b22919d6aa6bd98d96422e1a8d610d3442d4cf7731a575bd31fd43f0", - "docs/getting-started/nodes.md": "e50a2ca588c9d7cb836aa58e7b86ca685cd9da57742ceaee83ee0d549e538a94", - "docs/getting-started/self-hosted.md": "71aa6e0cb590c94cda98647a4867b611f325a51aff4b56689ed3e1a9531e1290", - "docs/self-hosted-native.md": "8fc6beccf28ace62e126faa03a923c669298b35213159c5d67b9ac3c7272741b", + "docs/getting-started/nodes.md": "13e1f1e867d3e361ff860960ceacc2dd5806e64f4176cd33f5e49f9a9f4d57e4", + "docs/getting-started/self-hosted.md": "4591e05bfa7657f647bedecd9db07b7086acd94b5548511c88f7e5e3567fdb11", + "docs/self-hosted-native.md": "a3b470461285f0aa9507b262ec8edf11e02f6683328d05206849debe1360b77f", "apps/web/public/onboarding/monitor-en.webp": "29dc220cb1250c7016b7c4bf7f30e9510b07c07b814a48c3aa9303b2d76f20b2", - "docs/web/README.md": "9fce295f6f6ff04acefe338679c1e54723e123dd0027a778202adfa9ab95b6c4", + "docs/web/README.md": "47159689b2488f0a94a1af8488bcf98b465e0cca4003d64a4699d7b4db24e086", "docs/api/web-management.md": "ec9a583c0a94845082ec31c7220ddcfb9aff7147c63fb36fa4c87463570f1b8c", "contracts/agents-api/runtime-observability-api.md": "cd46e777fe716a7e76374f4655c96dfbad9d8be1bfca6203ed6118ab87874c2b", - "docs/getting-started/operations.md": "2cba15fe56936cbc51e2ec8b8a888686273b21f729711e45c14ca6e32758663d", - "docs/user-guide.md": "a601c7f9df02c3bfe9c4ca3a43b91ab5721f3f8e904fccd116418dbdc1665a53", + "docs/getting-started/operations.md": "f5c0942003373aaf604fc0f5bb88e0d022f465f1ade2db2192975a173efe7d95", + "docs/user-guide.md": "1069d0f12aa42dde49693f25e8d964984e1c335fc67527123d31ee6a99617bab", "docs/development.md": "3e03e2666c92380d207ab53285e3b85fdcb042481c8ca76219ed08d629d52812", "contracts/agents-api/harness-onboarding.md": "2c744598f39c156f868418423abdf45d0b52e04b7debaa50ffc95b1b4bb91a87", "docs/runtime-protocol.md": "6baa332705743e34b8565613d743d1b30099d8af78159b06ad921ffa7e164a9f", "docs/sandbox-provider.md": "dd8c2c2b2e2acf4d6ae564f56ffaf5685d74a84fa7a7a15b4cad851015ee36ab", - "apps/docs/scripts/guides.json": "109374d4bf1a1d20d10ea85c9400ec6a2f9b62ca0fc6ee6030d3aab94a50d217" + "apps/docs/scripts/guides.json": "f4b2e58b64a89068a68a58ed1d8fe75893ee09d415e87391121e0e99bb1fbe3f" }, "outputs": { - "content/docs/index.mdx": "646fb88d73d81fe9a7efa3c066db430d064fcf966c60ecaa94e2a7e8fd18eead", - "content/docs/concepts.mdx": "ab0508c9d7c601695148dda6d3f4b709f9366bd4758ad92220f5839c84fcb64e", - "content/docs/execution-model.mdx": "6f60226d4f90bc92defb14c5b419d707bb3e419baea781f76eb35c68d3c8ef64", - "content/docs/install.mdx": "82f6b7015c2ddfeba16f53004eb6bbf9e5a5499fe97cbeee9b9244ac72ef694d", + "content/docs/index.mdx": "63318e9faa387a608efa11af7bd67917579df22a1e7fed00f907b4794112581a", + "content/docs/concepts.mdx": "cf4dc9e8838782bbc16539c8dec1ccb16680fe14cd1472eabceab6b79885f503", + "content/docs/execution-model.mdx": "bf528e34ace32ee1c256aaa4f2e31575bcbbd62d5c5efa7177ddc7b8e275becb", + "content/docs/install.mdx": "9cf6b03ae1c0c6caca768ea4c3ff2a47d7dfbfc3648cc7a73b7c848c7e257d7b", "content/docs/install-options.mdx": "3bbfa77af2c34f2b9f203079778b51ee9425624ca516c6392c859ee2add43591", - "content/docs/configure.mdx": "a4f96cf774494b104e3b1efe20d24cfef64d9a71284e547e36d93179472eeba7", - "content/docs/bootstrap-projects-keys.mdx": "477d76731eb09c14b2c1b09582d595258c1a74cc5b193e92644a340db859e6bd", - "content/docs/quickstart.mdx": "0ae6bbd5c488d39489aa2d83bd100e219b9ebb24b86d8dc1489089c197baa775", - "content/docs/public-api.mdx": "7902c5b44fdec1c097b4809634a70c554392cb58cc71fd68d6825b707888281e", + "content/docs/configure.mdx": "a39be53e21c65159af311724d7746e35a3c0dfcc9b87d5e79d01e54e7bb6d3ed", + "content/docs/bootstrap-projects-keys.mdx": "2ac720c071a0b37210c671b2d6fa704bb5720c2acaadac2650b893580965d2d8", + "content/docs/quickstart.mdx": "bab3cadd3cee86b6dcc11768cb81deb9d37c89521dfcace0a33d387e8d553815", + "content/docs/public-api.mdx": "055cb7e06d7647ff24e669a993ad1cfb806b2dfca51e12716f06df8fdf7ecac5", "content/docs/agents-and-tools.mdx": "9ffa5a5883847f2e4d3641bfd5975baf448fd371542797fd93204f69ea6df5e2", - "content/docs/sessions.mdx": "b0e127550c76b26d7649503dcf956044f4236eb798430b1000e356b103b02f1c", + "content/docs/sessions.mdx": "4f3a5e6e774f2ad687c1e00841eb716e1370c9206a8bd7a118325fa77594630c", + "content/docs/examples.mdx": "50dc70b46605d83df289cc555c064884645cd875cc46d0688782c1fac8752a0f", "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", + "content/docs/hosted-providers.mdx": "c504f42cea0c8c1ac6bd218a051b523cd8cd8609bd486233a787e2f4ff4f050c", + "content/docs/self-hosted-execution.mdx": "f190a4c40e532f3f24e8969c3df70f561b892ceb61b8b447eaf119312bffa071", + "content/docs/self-hosted-native.mdx": "e95c984383679bc1b2d016f864597eb625077e286228899c28eccbc5a89cc6b0", "public/images/source/apps/web/public/onboarding/monitor-en.webp": "29dc220cb1250c7016b7c4bf7f30e9510b07c07b814a48c3aa9303b2d76f20b2", - "content/docs/console.mdx": "356769e6017dbb78a9f42ee04d2d50c4bea6fa366a1bf69a062c04e549d63e0f", + "content/docs/console.mdx": "0a6a04c13a130a107f74c7c6cc518d24f6985780c94a6d0b9b0eb18384fb3253", "content/docs/admin-api.mdx": "d553f7712b22e2eb46bf7c84c2b7a1d67df51996e1533aca2451d24c2caf7628", "content/docs/observability.mdx": "595ab9f9918d04c058b64fa3a31d81913bbcbbc4d03138dca63a590979dde112", - "content/docs/troubleshooting.mdx": "6447708d4d73f9b7793b00215ddcd000ba411c41606db8987c4d848a64b1cd87", - "content/docs/user-guide.mdx": "97194cf016c237f604b7e626297790dc0ea8b570d4e1a866f7395f2813e0e607", + "content/docs/troubleshooting.mdx": "ef71d3a2d93915c55741869c40c9b2c0cb870922b60732ce65ecc4c38f60cbf0", + "content/docs/user-guide.mdx": "5389281b1fa4743479d0d4f49baa631793187d2484e7e55984efc8a9f96d1b55", "content/docs/development.mdx": "02136ed522b0545dc84fa210cf61d86058e85e1d3acd7890160bd1cce1a13a58", "content/docs/harness-onboarding.mdx": "115c6fcdc640c9260cbdbcb7315630045d1643c86a1b37a4c33a61ecc8053a9a", "content/docs/runtime-protocol.mdx": "59be1013b20c9236ec3480cdc29310e19bd08bbcf2d61d5bee45a9400b43c7be", diff --git a/apps/docs/scripts/guides.json b/apps/docs/scripts/guides.json index 7622273f9..69b1f3120 100644 --- a/apps/docs/scripts/guides.json +++ b/apps/docs/scripts/guides.json @@ -45,7 +45,7 @@ "slug": "quickstart", "source": "docs/getting-started/quickstart.md", "title": "Call the Agent API", - "description": "Use the pinned SDK, a Project API key and an explicit model provider to run a Session." + "description": "From a Project API key to a finished Session in three steps." }, { "slug": "public-api", @@ -62,8 +62,14 @@ { "slug": "sessions", "source": "docs/api/public-agent-api.md", - "title": "Sessions and public resources", - "description": "Agents, Sessions, Turns, events and resources in the pinned public contract." + "title": "Agents API guide", + "description": "Every public resource with OpenAI SDK and HTTP examples: Agents, Sessions, input, streaming, files, Skills, templates and Vaults." + }, + { + "slug": "examples", + "source": "docs/examples.md", + "title": "Examples", + "description": "Complete applications built on the Agents API, and what each one shows." }, { "slug": "environments-and-files", diff --git a/docs/api/README.md b/docs/api/README.md index 7df608a6c..89395baf3 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -1,45 +1,66 @@ # API documentation -Core serves three namespaces. Protected operations authenticate their own callers; -credentials cannot be substituted across these boundaries. Versioned native -installer downloads are public release content. +Core serves three namespaces. Each has one kind of caller and its own credential; +no credential works in another namespace. Versioned native 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`, `harness_config`, Session `installation`) | [Public API](public-agent-api.md) | +| `/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`) | [Agents API guide](public-agent-api.md) | | `/core/v1` | Core Web's server and operator scripts | [Core key](../getting-started/operations.md#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](web-management.md), [Core OpenAPI](../../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](../../services/agents-api/HOSTED-SANDBOX-MANAGER.md#register-a-host), [executor credentials](../../contracts/agents-api/environment-executor-credentials.md), [machine OpenAPI](../../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 -the Project's assets and execution principal; provenance retains the key that -performed each write. Projects and application keys live in PostgreSQL, never -deployment configuration. +A credential used in another namespace gets 401: a Project API key on `/core/v1` or +`/api/v1`, the Core key on `/v1` or `/api/v1`. How Projects and keys behave is in +[Projects own assets](../design-principles.md#projects-own-assets). -The browser talks only to Web's server: `/console/auth` and `/console/config`, -`/node-install/*`, the static pages, and `/core/v1/*`, which the server forwards -with the Core key after sign-in and same-origin checks. Users sign in to Web with -the Core key and get an HttpOnly session cookie; the browser never receives the -key. Core decides which `/core/v1` routes -exist; Web returns 404 for `/v1` and `/api/v1`, whatever credential a request -carries. - -The deployment's reverse proxy sends `/v1`, `/v1/*` and `/api/v1/*` to Core and -every other path, including `/core/v1/*`, to Web. Operator scripts call `/core/v1` -with the Core key on Core's loopback port, not through the public entry. +**Routing.** The reverse proxy sends `/v1` and `/api/v1` to Core and everything else +to Web ([proxy setup](../getting-started/install.md#https-and-the-reverse-proxy)). +Browsers reach `/core/v1` only through Web's server, which adds the Core key after +sign-in; Web returns 404 for `/v1` and `/api/v1`. Operator scripts call `/core/v1` +on Core's loopback port. Details: [Web and Core](web-management.md). ## Public API -Applications call every `/v1` route with a Project API key. The routes are exactly -the 58 method and path pairs in -[upstream-routes.json](../../contracts/agents-api/upstream-routes.json); the -[Public API guide](public-agent-api.md) groups them by resource. `/v1` has no -Core-only route. +Applications call `/v1` with a Project API key. The routes are exactly the 58 pairs +in [upstream-routes.json](../../contracts/agents-api/upstream-routes.json). The +[Agents API guide](public-agent-api.md) explains every resource with SDK and HTTP +examples. ## Core API All routes are under `/core/v1`. Core Web's server and operator scripts call them -with the Core key. +with the Core key. Most administrators use Web instead; call the API directly for +automation. + +### Common tasks + +Run these on the Core host, against Core's loopback port. The helper reads the key +from its file, keeping it off the command line: + +```sh +core() { # core METHOD PATH [JSON body] + curl -fsS -X "$1" "http://127.0.0.1:8091/core/v1$2" \ + -H @<(printf 'Authorization: Bearer %s\n' "$(cat ~/.oac/core/secrets/core.key)") \ + -H 'Content-Type: application/json' ${3:+-d "$3"} +} +``` + +| Task | Command | +| --- | --- | +| List Projects | `core GET /projects` | +| Create a Project | `core POST /projects '{"name": "billing-bot"}'` | +| Issue an API key (shown once, as `key`) | `core POST /projects/$PROJECT_ID/keys '{"name": "prod"}'` | +| Revoke a key | `core DELETE /projects/$PROJECT_ID/keys/$KEY_ID` | +| Archive a Project (revokes all keys) | `core POST /projects/$PROJECT_ID/archive` | +| See harnesses and their default models | `core GET /harnesses` | +| Set Codex's default model | `core PUT /harnesses/codex/model-configuration '{"model": "your-model-id", "model_provider": {"protocol": "responses", "base_url": "https://provider.example/v1", "api_key": "sk-..."}}'` | +| Issue an executor credential | See [self-hosted execution](../getting-started/self-hosted.md#operator-credential-management) | +| Installation facts, including the API base URL | `core GET /installation` | + +Errors use the [Core error envelope](../../contracts/agents-api/core-errors.md). + +### All routes | Routes | Contents | Contract | | --- | --- | --- | @@ -53,7 +74,7 @@ with the Core key. | `projects/{project_id}/environments/{environment_id}/executor-credentials[/{key_id}]` | Executor credentials for a self-hosted Environment | [Executor credentials](../../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](../../contracts/agents-api/installation.md) | | `metrics` | Core's own process metrics | [Core metrics](../../contracts/agents-api/core-metrics.md) | -| `sandbox/deployment[/reset]`, `sandbox/e2b/templates[/{template_id}/builds]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Core Web server or operator scripts with the Core key: sandbox deployment, read-only E2B template discovery, node enrollment tokens and nodes | [Sandbox deployment](../../contracts/agents-api/sandbox-deployment.md), [node operations](../../services/agents-api/HOSTED-SANDBOX-MANAGER.md), [node host history](../../contracts/agents-api/node-host-history.md) | +| `sandbox/deployment[/reset]`, `sandbox/e2b/templates[/{template_id}/builds]`, `sandbox/enrollment-tokens`, `sandbox/nodes[/{node_id}[/allocations]]` | Sandbox deployment, read-only E2B template discovery, node enrollment tokens and nodes | [Sandbox deployment](../../contracts/agents-api/sandbox-deployment.md), [node operations](../../services/agents-api/HOSTED-SANDBOX-MANAGER.md), [node host history](../../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](../../contracts/agents-api/model-execution.md#deployment-defaults) | ## Machine connection API @@ -97,17 +118,13 @@ support. The [coverage record](../../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](../../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. - -### Self-hosted installation +## Self-hosted installation -Authenticated Session creation/detail responses include short-lived commands in +Creating or reading a `self_hosted` Session returns short-lived install commands in `x_agents_core.installation`. Core Web reads the same commands at `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation`. Machine installers use `POST /api/v1/agent-daemon/installation` and its `/claim` -subroute with the installation Bearer authorization. Qualified artifacts beneath -`/api/v1/agent-daemon/install/{version}/` are public, immutable release content. -See [native self-hosted installation](../self-hosted-native.md) for expiry, retry, -credential ownership and platform rules. +subroute with the installation Bearer authorization. Qualified artifacts under +`/api/v1/agent-daemon/install/{version}/` are public, immutable release content. See +the [native Runtime guide](../self-hosted-native.md) for expiry, retry, credential +ownership and platform rules. diff --git a/docs/api/public-agent-api.md b/docs/api/public-agent-api.md index 37aed4732..2bd7b7fad 100644 --- a/docs/api/public-agent-api.md +++ b/docs/api/public-agent-api.md @@ -1,95 +1,569 @@ -# Public Agent API +# Agents API guide -Applications call Core directly with an API key issued inside a Project. They use -the public API to create and execute Agents, query history, and manage their assets. -They never use the Core key or the console's browser session cookie. +Core serves the [OpenAI Agents API](https://platform.openai.com/docs/api-reference) at +`/v1`. Use the official OpenAI SDK or plain HTTP. This guide shows both for every +common operation, and notes where Core differs from OpenAI. -## Authentication and base URL +New to the API? Run the [quickstart](../getting-started/quickstart.md) first. -Set `OPENAI_BASE_URL` to the installation's API base URL (`api_base_url` in -`GET /core/v1/installation`: the public URL followed by `/v1`) and `OPENAI_API_KEY` -to a Project API key; the official SDK reads both. Raw HTTP callers send -`Authorization: Bearer `. The fixed SDK supplies -`OpenAI-Beta: agents=v1` for the Beta Agents resources; raw HTTP callers must add -it. General Files and Skills endpoints do not require that Beta header. +## Before you start + +**Base URL and key.** Your administrator gives you the API base URL, such as +`https://core.example/v1`, and a Project API key. + +```sh +export OPENAI_BASE_URL=https://core.example/v1 +read -rs OPENAI_API_KEY && export OPENAI_API_KEY +``` + +**SDK.** Use the pinned version: + +```sh +pip install openai==3.13.0 +``` ```python from openai import OpenAI -client = OpenAI() # Reads OPENAI_API_KEY and OPENAI_BASE_URL. -page = client.beta.agents.list() +client = OpenAI() # reads OPENAI_BASE_URL and OPENAI_API_KEY +``` + +**HTTP.** Every request needs a Bearer key. Routes under `/agents` and `/vaults` also +need `OpenAI-Beta: agents=v1`; `/files` and `/skills` do not. The SDK sets both. The +HTTP examples below use this shell helper: + +```sh +oac() { # oac PATH [curl options]: call /agents or /vaults with the required headers + curl -sS "$OPENAI_BASE_URL$1" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: agents=v1" \ + -H "Content-Type: application/json" "${@:2}" +} +oac /agents +``` + +On a shared host, `-H @<(printf 'Authorization: Bearer %s\n' "$OPENAI_API_KEY")` +keeps the key out of the process list. + +## Resources at a glance + +| Resource | Path | What it is | +| --- | --- | --- | +| [Agents](#agents) | `/agents` | Reusable configuration: model, instructions, tools, harness | +| [Sessions](#sessions) | `/agents/sessions` | One agent conversation with its own Environment | +| [Input events](#send-input) | `/agents/sessions/{id}/events` (POST) | Messages, cancellation and tool results | +| [Event stream](#stream-events) | `/agents/sessions/{id}/events` (GET) | Live server-sent events | +| [Turns and Items](#turns-and-items) | `/agents/sessions/{id}/turns`, `/items` | Durable history | +| [Files](#files) | `/files`, `/agents/environments/{id}/files`, `/agents/sessions/{id}/artifacts` | Uploads, workspace files and outputs | +| [Skills](#skills) | `/skills` | Versioned capability bundles | +| [Environment Templates](#environment-templates) | `/agents/environments/templates` | Reusable workspace setup | +| [Vaults](#vaults) | `/vaults` | Write-only credentials for MCP servers | +| Subagents | `/agents/sessions/{id}/subagents` | Read-only child work; see [subagents](../../contracts/agents-api/subagents.md) | + +Core has exactly the routes of the pinned SDK, listed in +[upstream-routes.json](../../contracts/agents-api/upstream-routes.json). It adds no +route; its additions live in [`x_agents_core`](#core-extensions-x_agents_core). + +## Conventions + +### Pagination + +Lists return: + +```json +{"object": "list", "data": [...], "has_more": true, "first_id": "...", "last_id": "..."} +``` + +| Parameter | Meaning | +| --- | --- | +| `limit` | 1–100, default 20 | +| `order` | `desc` (default) or `asc` | +| `after` | Pass the previous page's `last_id` | + +The SDK pages for you: + +```python +for session in client.beta.agents.sessions.list(limit=100): + print(session.id, session.status) +``` + +```sh +oac "/agents/sessions?limit=100&after=$LAST_ID" +``` + +Two lists differ: `GET /files` returns up to 10,000 files at once, and workspace +files use an opaque `page` token (see [Workspace files](#workspace-files)). + +### Idempotency + +Send an `Idempotency-Key` (up to 128 bytes) when creating a Session or sending input. +A retry with the same key and body returns the original result instead of doing the +work twice. The same key with a different body fails with 409 `idempotency_conflict`. + +```python +import uuid + +key = str(uuid.uuid4()) # store it before sending, reuse it on retry +client.beta.agents.sessions.events.create(session_id, events=[...], idempotency_key=key) +client.beta.agents.sessions.create(environment=..., extra_headers={"Idempotency-Key": key}) +``` + +**After a lost response,** retry with the same key, then read the Session, Turns and +Items. Never resend without the key. Core keeps creation keys even after the Session +is deleted. + +> Core difference: OpenAI creates a new Session for each create request even with the +> same key. Core returns the original. + +### Errors + +```json +{"error": {"type": "invalid_request_error", "message": "...", "code": "model_provider_required", "param": "x_agents_core.model_provider"}} +``` + +| Status | Common codes | Meaning | +| --- | --- | --- | +| 400 | `invalid_request_error`, `invalid_beta`, `model_provider_required`, `unsupported_or_invalid_configuration` | Fix the request. `invalid_beta` means a missing or wrong `OpenAI-Beta` header | +| 401 | `invalid_api_key` or none | Wrong or missing key, or a key from another namespace | +| 404 | | Missing, or belongs to another Project. The two look the same | +| 405 | `unsupported_operation` | Core doesn't support this operation | +| 409 | `conflict_error`, `idempotency_conflict` | State conflict, for example deleting a busy Session | +| 413 | | Body too large | +| 503 | | Temporarily uncertain; read state before retrying | + +Every response carries `X-Request-Id`; include it when reporting a problem. + +### Core extensions: `x_agents_core` + +Core runs several harnesses and accepts your own model access. Those settings are the +only additions to the OpenAI shapes, and they sit inside `x_agents_core`: + +| Field | Where | Value | +| --- | --- | --- | +| `harness` | Agent, or a Session's inline `agent` | `codex`, `claude_sdk` or `mcode` | +| `model_provider` | Agent, or Session creation (top level) | `protocol` (`responses`, `anthropic` or `chat_completions`), `base_url`, `api_key`, and for `mcode` also `context_window` and `max_output_tokens` | +| `harness_config` | Agent, inline `agent`, or Session creation (top level, wins) | The harness's native model parameters, such as Codex's `model_reasoning_effort` | +| `installation` | Read-only, on `self_hosted` Sessions | Short-lived install commands for your machine; see [self-hosted execution](../getting-started/self-hosted.md) | + +Any other member is rejected with 400. `api_key` is write-only: reads return +`api_key_configured`. `harness_config` replaces the whole object; `{}` clears it. With the SDK, pass these through `extra_body`. How to pick a +harness and model, and which provider a Session uses, is in the +[user guide](../user-guide.md#choose-a-harness-and-a-model). + +## Agents + +An Agent is saved configuration. Sessions copy it when they start, so editing an +Agent affects only new Sessions. + +```python +agent = client.beta.agents.create( + model="your-model-id", + name="Reviewer", + instructions="Review code changes and report problems.", + extra_body={"x_agents_core": {"harness": "codex"}}, +) +``` + +```sh +oac "/agents" -d '{ + "model": "your-model-id", + "name": "Reviewer", + "instructions": "Review code changes and report problems.", + "x_agents_core": {"harness": "codex"} +}' +``` + +```json +{"id": "agent_...", "object": "agent", "model": "your-model-id", "name": "Reviewer", + "instructions": "...", "tools": [], "metadata": {}, "created_at": 1790000000, + "x_agents_core": {"harness": "codex"}} ``` -This read does not execute a model. See the [real execution quickstart](../getting-started/quickstart.md) -for separate model access configuration and a complete Session example. +| Operation | SDK | HTTP | +| --- | --- | --- | +| Create | `agents.create(...)` | `POST /agents` | +| Read | `agents.retrieve(id)` | `GET /agents/{id}` | +| Update | `agents.update(id, ...)` | `POST /agents/{id}` | +| List | `agents.list()` | `GET /agents` | +| Delete | `agents.delete(id)` | `DELETE /agents/{id}` | + +(`agents` is `client.beta.agents` throughout.) + +- **Update** changes only the fields you send. `metadata` replaces all pairs; `null` + clears `name` or `instructions`. +- **Delete** keeps existing Sessions. +- **Tools** are functions, MCP servers, `tool_search` (Claude) and `web_search` with + `mode: "disabled"`. Support depends on harness and Environment; see + [execution tools](../../contracts/agents-api/execution-tools.md). + +## Sessions + +A Session is one conversation with a fixed configuration and its own Environment. + +### Create a Session + +```python +session = client.beta.agents.sessions.create( + environment={"type": "openai_hosted"}, + agent_id=agent.id, + input="Review the files in /workspace and summarize the risks.", + metadata={"ticket": "T-123"}, +) +``` + +```sh +oac "/agents/sessions" -H "Idempotency-Key: $(uuidgen)" -d '{ + "environment": {"type": "openai_hosted"}, + "agent_id": "agent_...", + "input": "Review the files in /workspace and summarize the risks.", + "metadata": {"ticket": "T-123"} +}' +``` -All keys in a Project share assets and Session creator identity. Revoking one key -leaves the others valid; archiving the Project revokes all its keys. The optional -`OpenAI-Organization` and `OpenAI-Project` headers must match `core` and -`proj_` respectively. Do not send a key's UUID as the project scope. +Returns 201 with the Session: -## Public resources +```json +{"id": "sess_...", "object": "agent.session", "status": "in_progress", + "agent": {"model": "...", ...}, "environment": {"id": "env_...", "type": "openai_hosted", ...}, + "metadata": {"ticket": "T-123"}, "required_actions": [], "vault_ids": [], + "created_at": 1790000000, "last_active_at": 1790000000} +``` -Paths are relative to `/v1`. Detailed fields, union types and response shapes are -in the [public OpenAPI](../../contracts/agents-api/openapi.yaml), fixed SDK source -and linked semantic records. The [resource inventory](../../contracts/agents-api/README.md#upstream-resource-inventory) -lists each operation and its coverage. +| Field | Meaning | +| --- | --- | +| `environment` | Required. Where the agent works; see the table below | +| `agent_id` or `agent` | A saved Agent, or an inline Agent object (same fields as create). An inline Agent on `openai_hosted` or `none` may omit `model` to use the installation default | +| `input` | The first message: a string or a message array. Optional for `openai_hosted` and `self_hosted` | +| `metadata` | Your own string key-value pairs | +| `vault_ids` | [Vaults](#vaults) whose credentials MCP servers may use | +| `stream` | `true` returns [server-sent events](#stream-events) instead of JSON | +| `x_agents_core.model_provider` | This Session's model access, if not from the Agent or the default | -| Resource | Route family | Semantics | +| `environment.type` | Runs on | Notes | | --- | --- | --- | -| Agents | `/agents` | Reusable configuration, CRUD and lists | -| 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](../../contracts/agents-api/subagents.md) | -| Environments and workspace Files | `/agents/environments`, nested `/files` | [Environment state](../../contracts/agents-api/environments.md) and [workspace access](../../contracts/agents-api/environment-files.md) | -| Environment Templates | `/agents/environments/templates` | [Reusable initialization](../../contracts/agents-api/environment-templates.md) | -| Source Files | `/files` | [Uploaded content resources](../../contracts/agents-api/source-files.md), distinct from live workspace files | -| Skills and versions | `/skills`, nested `/versions` | [Bundles and versions](../../contracts/agents-api/file-resource-semantics.md) | -| Vaults and Credentials | `/vaults`, nested `/credentials` | [Scoped write-only credential storage](../../contracts/agents-api/environments.md) | - -SSE is live, not a historical replay service. After a disconnect, query the Session, -Turns and Items to reconcile state. An accepted request is not proof of completed -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](../../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 | +| `openai_hosted` | A sandbox Core creates (node or E2B) | Optional `network`, `packages`, `files`, `skills`, `plugins`, `setup_commands`, or a template | +| `self_hosted` | Your machine | Requires an absolute `workspace_directory`. The response carries install commands in `x_agents_core.installation`; see [self-hosted execution](../getting-started/self-hosted.md) | +| `none` | An existing device connection | `input` required; uses the default model only | + +### Session status + +| `status` | Meaning | +| --- | --- | +| `in_progress` | A Turn is running | +| `idle` | Waiting for input | +| `requires_action` | Waiting for you: a [function result](#function-tools) or a self-hosted machine to connect | +| `failed` | The Environment could not be prepared. See `error` | + +### Update, list and delete + +```python +client.beta.agents.sessions.update(session.id, metadata={"ticket": "T-124"}) +for s in client.beta.agents.sessions.list(agent_id=agent.id): + print(s.id) +client.beta.agents.sessions.delete(session.id) +``` + +| Operation | HTTP | Notes | | --- | --- | --- | -| `x_agents_core.harness` | Saved Agent create, update and read; the inline Session `agent`; the Session's effective `agent` | [Harness selection](../../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](../../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 -`/core/v1`, which only the Core key can call (see the [API index](README.md)). - -A Session's model provider comes from the Session's `x_agents_core.model_provider`, -then a saved Agent's, then the deployment default that the administrator sets per -harness. The deployment default applies to `openai_hosted` and `none` Sessions, -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](../../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 -default harness omits `agent.x_agents_core`. `/v1` has no execution-configuration -read. - -`openai_hosted` keeps the official wire name and means Core-managed compute here. -The deployment chooses E2B or its own Docker/microsandbox nodes. A public -`self_hosted` Environment uses caller-owned compute and the same colocated -Runtime on Linux, macOS or Windows; managed Providers remain Linux-only. Native -Runtime execution uses the launching user's permissions without an inner sandbox. -See [native installation and validation status](../self-hosted-native.md). -For a `self_hosted` Session, the deployment operator issues the -Environment's executor credential with the Core key; see -[executor credentials](../../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. +| Read | `GET /agents/sessions/{id}` | | +| Update | `POST /agents/sessions/{id}` | Only `metadata` | +| List | `GET /agents/sessions?agent_id=...` | Filter by Agent is optional | +| Delete | `DELETE /agents/sessions/{id}` | Only when `idle` or `failed` with nothing pending; otherwise 409. Cancel first | + +## Send input + +All input goes to one endpoint as a list of events. It returns 202 once the input is +stored, before the agent reads it. + +### Send a message + +```python +client.beta.agents.sessions.events.create( + session.id, + events=[{ + "type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Now fix the first risk."}]}], + }], + idempotency_key=key, +) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -H "Idempotency-Key: $KEY" -d '{ + "events": [{"type": "agent.session.input.message", + "input": [{"role": "user", "content": [{"type": "input_text", "text": "Now fix the first risk."}]}]}] +}' +``` + +- **When idle,** a message starts a new Turn. **While a Turn runs,** it joins that + Turn (steering); it does not start a parallel task. +- **Content** is `input_text`, plus `input_image` as an inline PNG or JPEG data URI. + Images work with Codex and Claude Code, on `none` and Docker sandboxes only. The + whole request is limited to 1 MiB. +- Full rules: [message input](../../contracts/agents-api/message-input.md). + +### Cancel + +```python +client.beta.agents.sessions.events.create(session.id, events=[{"type": "agent.session.input.cancel"}]) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -d '{"events": [{"type": "agent.session.input.cancel"}]}' +``` + +The Turn is cancelled when it reaches `cancelled`, not when the request returns. A +cancel while idle does nothing. + +## Stream events + +`GET /agents/sessions/{id}/events` is a server-sent event stream. It is **live only**: +events sent while you were disconnected are not replayed. Open it before sending +input, and recover gaps from [Turns and Items](#turns-and-items). + +```python +with client.beta.agents.sessions.events.stream(session.id) as stream: + for event in stream: + if event.type == "agent.session.turn.output_text.delta": + print(event.delta, end="", flush=True) + elif event.type in {"agent.session.turn.completed", "agent.session.turn.failed", "agent.session.turn.cancelled"}: + break +``` + +```sh +oac "/agents/sessions/$SESSION_ID/events" -N +``` + +```text +event: agent.session.turn.output_text.delta +data: {"type": "agent.session.turn.output_text.delta", "item_id": "item_...", "delta": "Hello", ...} +``` + +| Event | When | +| --- | --- | +| `agent.session.turn.created`, `.in_progress` | A Turn starts | +| `agent.session.turn.item.added`, `.item.done` | An Item (message, tool call, …) starts or finishes | +| `agent.session.turn.output_text.delta`, `.done` | Assistant text, piece by piece | +| `agent.session.turn.completed`, `.failed`, `.cancelled` | A Turn ends. Carries `usage` | +| `agent.session.in_progress`, `.idle`, `.requires_action`, `.failed` | Session status changes | +| `agent.session.subagent.*` | Child work starts or ends | +| `error` | A stream-level error | + +The stream stays open across Turns. To stream one Turn and handle +[function calls](#function-tools) automatically, the SDK's `sessions.stream` helper +does both. + +**Stream the creation itself** with `stream=True` on `sessions.create`. You get +`agent.session.created` first, and the stream ends at the first `idle` or `failed`. + +**Reconnecting:** resubscribe, then read Items and drop any you already have by ID. +Details: [history and events](../../contracts/agents-api/history-events-usage.md). + +## Turns and Items + +A Turn is one piece of work started by input. Items are its recorded content: +messages, reasoning, tool calls and their results. Both are durable; read them to +check results or recover after a disconnect. + +```python +turns = client.beta.agents.sessions.turns.list(session.id, order="desc") +latest = turns.data[0] +print(latest.status, latest.usage) +for item in client.beta.agents.sessions.items.list(session.id, order="asc"): + print(item.type) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/turns?order=desc&limit=1" +oac "/agents/sessions/$SESSION_ID/items?order=asc" +``` + +| Turn `status` | Meaning | +| --- | --- | +| `queued`, `in_progress` | Not finished | +| `waiting` | Waiting for a function result | +| `completed`, `failed`, `cancelled` | Finished | + +- **Usage** (`input_tokens`, `output_tokens`, `total_tokens`, …) may arrive after the + Turn ends. Treat `null` as "not yet known", not zero. +- Turn lists contain top-level Turns only. Read child work under `/subagents`. + +## Function tools + +Declare a function on the Agent. When the model calls it, the Session enters +`requires_action` and the Turn `waiting` until you return a result. + +```python +agent = client.beta.agents.create( + model="your-model-id", + tools=[{ + "type": "function", + "name": "get_weather", + "description": "Current weather for a city", + "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}, + }], +) + +def get_weather(args): + return f"Sunny in {args['city']}" + +with client.beta.agents.sessions.stream( + session.id, input="What's the weather in Paris?", tool_handlers={"get_weather": get_weather} +) as stream: + for event in stream: + pass # the helper submits each result and stops when the Turn ends +``` + +Without the helper, read the call from `session.required_actions`, then send: + +```sh +oac "/agents/sessions/$SESSION_ID/events" -d '{ + "events": [{"type": "agent.session.input.tool_result", + "turn_id": "turn_...", "call_id": "call_...", "success": true, "output": "Sunny in Paris"}] +}' +``` + +Resending the same result is safe. A different result for the same call, or one sent +after cancellation, fails with 409. MiniMax Code doesn't support public functions. + +## Files + +Three kinds of file serve different purposes: + +| Kind | Use it to | Path | +| --- | --- | --- | +| [Source Files](#source-files) | Upload bytes once and reference them by ID | `/files` | +| [Workspace files](#workspace-files) | Put files into a running Session's workspace, or list it | `/agents/environments/{id}/files` | +| [Artifacts](#artifacts) | Download what the agent produced | `/agents/sessions/{id}/artifacts` | + +### Source Files + +```python +f = client.files.create(file=open("data.csv", "rb"), purpose="user_data") +``` + +```sh +curl "$OPENAI_BASE_URL/files" -H "Authorization: Bearer $OPENAI_API_KEY" \ + -F purpose=user_data -F file=@data.csv +``` + +Only `purpose=user_data` is accepted, up to 512 MiB. No Beta header. Their content +cannot be downloaded again; use the ID in workspace files or templates. + +### Workspace files + +Copy a file into the workspace of the Session's Environment (`session.environment.id`): + +```python +env_id = session.environment.id +client.beta.agents.environments.files.create(env_id, type="file_id", file_id=f.id, path="/workspace/data.csv") +client.beta.agents.environments.files.create(env_id, type="inline", data="aGVsbG8K", path="/workspace/hello.txt") +page = client.beta.agents.environments.files.list(env_id, path="/workspace") +``` + +```sh +oac "/agents/environments/$ENV_ID/files" -d '{"type": "file_id", "file_id": "file_...", "path": "/workspace/data.csv"}' +``` + +- `inline` data is base64, up to 5 MiB decoded; `file_id` up to 50 MiB. +- Parent directories are created. An existing file is never overwritten (400). +- The list shows regular files in one directory, not recursively. It pages with a + `page` token and returns `next`. + +### Artifacts + +When a Turn completes, Core captures the regular files under the workspace's +`outputs/` directory. Artifacts stay readable after the Environment is gone. + +```python +for a in client.beta.agents.sessions.artifacts.list(session.id): + data = client.beta.agents.sessions.artifacts.content(a.id, session_id=session.id) + data.write_to_file(a.path.rsplit("/", 1)[-1]) +``` + +```sh +oac "/agents/sessions/$SESSION_ID/artifacts" +oac "/agents/sessions/$SESSION_ID/artifacts/$ARTIFACT_ID/content" -o report.md +``` + +Each Artifact has `path`, `size_bytes`, `turn_id` and `environment_id`. Deleting one +leaves the workspace file alone. + +## Skills + +A Skill is a versioned bundle of instructions and files an agent can use. Upload a +directory or a ZIP; each upload is a version. + +```sh +curl "$OPENAI_BASE_URL/skills" -H "Authorization: Bearer $OPENAI_API_KEY" -F files=@my-skill.zip +``` + +```python +skill = client.skills.create(files=[("my-skill/SKILL.md", open("my-skill/SKILL.md", "rb"))]) +client.skills.versions.create(skill.id, files=[...], default=True) +``` + +- No Beta header. Up to 50 Skills; 5 MiB compressed, 20 MiB expanded per archive. +- SDK 3.13.0 drops a single ZIP file from the upload; use HTTP for a ZIP. +- Attach Skills to a Session through its `environment.skills` or a + [template](#environment-templates). + +Details: [Source Files and Skills](../../contracts/agents-api/source-files.md). + +## Environment Templates + +A template saves workspace setup for reuse by `openai_hosted` Sessions: + +```python +template = client.beta.agents.environments.templates.create( + name="python-data", + network={"access": "restricted", "allowed_domains": ["pypi.org", "files.pythonhosted.org"]}, + packages={"python": ["pandas"]}, + setup_commands=["mkdir -p /workspace/outputs"], +) +``` + +| Field | Meaning | +| --- | --- | +| `network` | `access`: `enabled`, `disabled`, or `restricted` to 1–100 exact hosts in `allowed_domains`. A Session can only narrow it | +| `packages` | `npm` and `python` packages. `system` packages are rejected: bake them into the image | +| `setup_commands`, `env` | Run and set at preparation. Never returned by reads | +| `files`, `skills`, `plugins` | Initial content. Up to 50 files, 10 MiB inline in total | + +A Session freezes the template when it starts. Details: +[Environment Templates](../../contracts/agents-api/environment-templates.md). + +## Vaults + +Vaults hold credentials for HTTP MCP servers: a `static_bearer` token or an `mcp_oauth` +token with optional refresh. Tokens are write-only. + +```python +vault = client.beta.agents.vaults.create(name="github") +client.beta.agents.vaults.credentials.create( + vault.id, name="github-token", + auth={"type": "static_bearer", "token": "ghp_...", "mcp_server_url": "https://api.githubcopilot.com/mcp/"}, +) +session = client.beta.agents.sessions.create(environment={"type": "none"}, input="...", vault_ids=[vault.id], agent_id=agent.id) +``` + +The HTTP path is `/vaults`, with the Beta header. A credential is used when an MCP +server's URL matches its `mcp_server_url` exactly, or when the tool names its +`credential_id`. Service-origin MCP works with Codex and Claude Code on `none` +Sessions only. + +## Limits and differences from OpenAI + +| Area | Core behavior | +| --- | --- | +| Routes | Exactly the pinned SDK's routes; no extra routes | +| Extensions | Only `x_agents_core.harness` and `x_agents_core.model_provider` | +| Session create idempotency | Same key returns the original Session | +| Event stream | Live only; no replay, `Last-Event-ID` ignored | +| Tools | No enabled `web_search`; no multi-agent with functions; MiniMax Code has no public functions | +| Images | Inline PNG/JPEG only; Codex and Claude Code; `none` and Docker sandboxes | +| Packages | `packages.system` rejected | + +Per-operation status and harness differences are in the +[coverage record](../../contracts/agents-api/README.md). The exact schemas are in the +[public OpenAPI](../../contracts/agents-api/openapi.yaml). diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 000000000..38ca63672 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,60 @@ +# Examples + +Complete applications built on the [Agents API](api/public-agent-api.md). Each one +runs against a real Core installation with a Project API key. + +| Example | What it shows | +| --- | --- | +| [Parsar Agent workbench](#parsar-agent-workbench) | A product UI: models, Skills, MCP, reusable Agents, and Sessions on any runtime | + +## Parsar Agent workbench + +A small single-user product built on Core. You save model providers, Skills and MCP +servers, combine them into Agents, then start Sessions in a managed sandbox, with +no workspace, or on your own machine. + +Source: [`example/parsar`](../example/parsar/README.md). + +### Run it + +You need Node 22.13+, pnpm 10.30.3, a running Core with a default model, and a Project +API key. + +```sh +export OAC_EXAMPLE_CORE_URL='https://core.example' # origin, without /v1 +export OAC_EXAMPLE_PROJECT_KEY='' +pnpm install --frozen-lockfile +pnpm --filter @oac/parsar-example dev +``` + +Open . The example [README](../example/parsar/README.md) covers +storage, a production build, tests and connecting your own machine. + +### What to look at + +Each feature maps to one part of the API. Read the code next to the guide section: + +| Feature | API used | Guide | Code | +| --- | --- | --- | --- | +| Server-side key and headers | Bearer key, `OpenAI-Beta`, route allowlist | [Before you start](api/public-agent-api.md#before-you-start) | [`server.mjs`](../example/parsar/server.mjs) | +| Agents with a harness and model | `x_agents_core.harness`, `model_provider` | [Core extensions](api/public-agent-api.md#core-extensions-x_agents_core) | [`server/sessions.mjs`](../example/parsar/server/sessions.mjs) | +| Sessions on three runtimes | `openai_hosted`, `none`, `self_hosted` with `workspace_directory` | [Create a Session](api/public-agent-api.md#create-a-session) | [`server/sessions.mjs`](../example/parsar/server/sessions.mjs) | +| Crash-safe Session creation | `Idempotency-Key`, recovery from a lost response | [Idempotency](api/public-agent-api.md#idempotency) | [`server/sessions.mjs`](../example/parsar/server/sessions.mjs) | +| Live replies | Event stream, text deltas, reconnect and reconcile | [Stream events](api/public-agent-api.md#stream-events) | [`src/lib/live-session.ts`](../example/parsar/src/lib/live-session.ts) | +| Follow-ups and cancel | Input events with idempotency keys | [Send input](api/public-agent-api.md#send-input) | [`src/Composer.tsx`](../example/parsar/src/Composer.tsx) | +| History | Paging Turns and Items | [Pagination](api/public-agent-api.md#pagination) | [`src/lib/api.ts`](../example/parsar/src/lib/api.ts) | +| Skills and versions | `/skills`, default version | [Skills](api/public-agent-api.md#skills) | [`src/Skills.tsx`](../example/parsar/src/Skills.tsx) | +| Connect your own machine | Environment status, executor credential | [Self-hosted execution](getting-started/self-hosted.md) | [`src/ConnectMachine.tsx`](../example/parsar/src/ConnectMachine.tsx) | + +### Not covered + +Vaults and MCP authentication, OAuth, Session deletion, and MiniMax Code on your +own machine. + +## Add an example + +Put it in its own directory under [`example/`](../example/README.md) with a README +covering how to run it and which API features it shows, then add a row to the +table above. Keep examples on the public API with a Project API key: never the Core +key or private routes. Repository rules for examples are in +[CONTRIBUTING.md](../CONTRIBUTING.md#repository-boundary). diff --git a/example/README.md b/example/README.md index fa984151e..34ed492b4 100644 --- a/example/README.md +++ b/example/README.md @@ -1,4 +1,8 @@ # Application examples -[Parsar](parsar/README.md) is a small Agent workbench using OpenAgentCore public -resources. Reuse Agent configurations to start independent runtime-bound Sessions. +Complete applications on the OpenAgentCore public API. See the +[examples guide](../docs/examples.md) for what each one shows and how to run it. + +| Example | Summary | +| --- | --- | +| [Parsar](parsar/README.md) | Agent workbench: models, Skills, MCP, reusable Agents and Sessions on any runtime | diff --git a/example/parsar/README.md b/example/parsar/README.md index 08ea3006b..d795cf169 100644 --- a/example/parsar/README.md +++ b/example/parsar/README.md @@ -92,6 +92,19 @@ Session deletion/archival is outside this example. Skill deletion is a separate explicit Core operation. Earlier templates and instances become Agent configs on startup; they are never presented as actual Sessions. +A few more implementation details: + +- **Providers and models** are saved together in one SQLite transaction. Editing + reads a Provider and its models as one snapshot; changing a model advances the + Provider's revision. +- **Browser calls** use `OpenAIAgentsClient`; only Session creation goes through a + small server adapter. Closing the browser aborts the upstream stream, never the + running Session. +- **Workspaces:** hosted Sessions each get their own. User-machine Sessions use the + selected host directory, so the same path means shared files. +- **Skills on a user machine** come only from local capability directories; managed + Skill references are rejected explicitly, not ignored. + ## Validation ```sh @@ -133,9 +146,7 @@ Agent organization informs the product flow; no Multica code is copied. ## Connect a user machine -This branch builds on `codex/qualified-release-promotion-20260928` (native daemon -support). Run a matching Core and daemon version; the older preview Core does not -qualify this workflow. The optional unified Harness installer PR is not included. +Run a matching Core and daemon version. Create a user-machine runtime and start a Session with an Agent using Codex or Claude Code. No initial Turn is sent. Open **Connect user machine**, obtain the diff --git a/scripts/name-allowlist.json b/scripts/name-allowlist.json index 5b97d90ad..9831f2413 100644 --- a/scripts/name-allowlist.json +++ b/scripts/name-allowlist.json @@ -819,6 +819,16 @@ "regex": "example/parsar", "reason": "The explicitly named Parsar application example retains product branding; it does not rename the Core runtime." }, + { + "path": "docs/examples.md", + "regex": "(?i)parsar", + "reason": "The examples guide describes the explicitly named Parsar application example; it does not rename the Core runtime." + }, + { + "path": "apps/docs/content/docs/examples.mdx", + "regex": "(?i)parsar", + "reason": "Generated copy of docs/examples.md: The examples guide describes the explicitly named Parsar application example; it does not rename the Core runtime." + }, { "path": "pnpm-lock.yaml", "regex": "(?:example/parsar|@oac/parsar-example)",