Agent configuration contract
Reusable configuration, optional long-term memory, consistent execution semantics.
中文Open the Agents Web UI prototype
Edit configuration, select models and memory, save or restore drafts, and preview trial or new conversations. Uses existing animated icons and themes; all data is illustrative.
Scope and object model
An Agent is reusable execution configuration with optional persistent state. A task-specific role, persona, dedicated model, workspace, long-term memory, or background schedule is not required. The saved Agents page and an inline Python configuration express the same execution contract.
| Object | Identity and lifetime | Boundary |
|---|---|---|
| AgentConfig | An immutable value for one resolution; may be inline and unnamed | No implicit persistence, session or memory allocation |
| AgentSpec | Saved ID, display name, revision and AgentConfig fields | Metadata and configuration, not a running worker |
| Execution | Existing run/job ID and immutable effective configuration | One invocation; multiple executions may reference the same Agent |
| Session / DAG | Existing conversation and execution history | History reuse is chosen separately from Agent selection |
| Memory space | Stable store reference with access policy | Optional; never inferred solely from a matching display name |
Keep AgentSpec as the persisted envelope. AgentConfig is its typed executable projection, not a second on-disk registry. Resource governance, the context engine, memory backends and task control remain their existing subsystems.
Verified source and present gaps
| Area | Observed implementation | Design gap |
|---|---|---|
| Saved configuration | AgentSpec / manager stores model, effort, instructions, tools, skills, MCP, identity and session policy | No explicit per-Agent memory policy or configuration revision |
| Agents UI | AgentsPage has six tabs and one draft | Free-text model fields; fixed effort options; no memory panel or effective-value provenance |
| Function execution | agent() and llm() use Runtime.exec | No saved-Agent/config selection arguments |
| Delegation | agent tool accepts agent_id, clean/inherit, background and to | Share configuration resolution without merging inline calls and durable dispatch semantics |
| Management writes | Agent routes compare optional updated_at before manager update; tools saved separately | Comparison outside write lock and multiple writes do not establish atomic whole-config CAS |
| Memory | MemoryConfig and MemoryBackend expose global read/injection/writer controls | Per-execution policy and scoped binding must cover all ingestion paths |
| Workspace | workspace helpers seed instruction files | An Agent directory is not an isolation guarantee |
These are source observations, not fresh end-to-end acceptance. Existing UI was inspected in the installed default App; new target controls are not installed. The checkout has no usable CodeGraph index, so the audit uses scoped file reads. No new runtime behavior is claimed.
Configuration schema and defaults
| Field | Target semantics | Default / validation |
|---|---|---|
| schema_version / revision | Persisted schema format / monotonic saved-config revision | New format 2; revision is assigned by the manager |
| name / description / identity | Saved display name, optional description and channel identity | Role and description optional; immutable ID for saved records only |
| model / thinking_effort | Provider-qualified reference and supported reasoning level | Unset inherits; explicit unsupported values block execution |
| system_prompt / instruction_files | Inline instructions and allowlisted Agent workspace file references | Omission inherits; empty prompt clears this layer only |
| tools / skills / mcp | Independent capability policies with stable references | Modes inherit, all, selected, none; selected empty means none |
| memory | Mode, read_spaces, write_space, required | New Agents and anonymous configs explicitly off; existing Agents migrate to legacy behavior |
| context | history: inherit, clean, selected; selected node references | Legacy inline calls retain inherited view; named/inline config switches default clean |
| environment | cwd reference and existing sandbox profile reference | Inherited environment; missing explicit path fails before tools run |
| limits | References/overrides for supported resource-governance limits | Unset inherits; effective child cap never exceeds parent cap |
| session policy | Existing channel scope/reset fields plus explicit timezone reference | Does not decide function history or memory access |
Do not add arbitrary provider parameters, inheritance between named Agents, custom execution engines, or arbitrary memory plugins to the first implementation. Inline configs use system defaults, not hidden fields from the caller’s saved Agent. Empty description is valid. A saved Agent only needs a name; choosing a model is optional if a usable default exists.
Wire shape and typed boundaries
Proposed wire shape; identifiers are placeholders. Keep the current flat AgentSpec envelope, adding typed fields without nesting a second config registry. POST accepts name plus optional executable fields; id/revision/timestamps are server-assigned unless a valid explicit legacy ID is provided. AgentConfig contains executable fields only. Export/import excludes server metadata and assigns a fresh saved identity. The Python package exports AgentConfig alongside agent and llm; it accepts a provider-qualified model string as shorthand and normalizes it to the persisted provider/id object.
{
"schema_version": 2,
"id": "general",
"name": "General",
"revision": 1,
"model": {"provider": "provider-id", "id": "model-id"},
"system_prompt": "",
"tools": {"mode": "selected", "allowed": ["tool_a"], "disabled": []},
"skills": {"mode": "none"},
"mcp": {"mode": "none"},
"memory": {"mode": "off"},
"context": {"history": "clean"}
}
PATCH /api/agents/general
{
"expected_revision": 1,
"system_prompt": "Use concise answers.",
"memory": {"mode": "off"},
"reset_fields": ["model", "thinking_effort"]
}
The memory policy contains mode, optional read_spaces: string[], write_space: string and required: boolean (default false). Active read modes require at least one authorized read space; read_write requires exactly one readable write target. Off makes bindings inactive without deleting stored data; the editor may retain dormant bindings in its draft, but the effective runtime receives no memory grants. An instruction_files item contains path: string and required: boolean (default true), restricted to the Agent workspace. Unknown fields, invalid types and a field present in both reset_fields and changes are rejected before writing. Readiness is returned separately from stored configuration.
One resolver; explicit merge rules
Resolve the base from exactly one source: explicit agent_id, explicit config, ambient Agent, or system default, in that order. agent_id and config are mutually exclusive. Session overrides apply only while remaining on the same Agent identity. A named-Agent/config switch does not inherit the old Agent’s model, prompt, tools or memory bindings. Authorized invocation overrides then replace the relevant fields. Apply authority constraints last, and recheck revocations at every effectful boundary.
| Value / operation | Meaning |
|---|---|
| Omitted / UNSET | Inherit; PATCH omission leaves storage unchanged |
| Empty string | Clear prompt/description; model clearing uses reset_fields instead of an empty invalid model ID |
| Empty selected list | Explicit empty scope; never interpreted as all |
| mode=none / memory.mode=off | Explicit disable; not inheritance |
| reset_fields | Delete local override and expose the base value; JSON null is rejected |
| Lists / policy objects | Replace complete list/policy atomically; no implicit union |
| Scalar object fields | Patch explicitly named leaves; normalize to a complete policy before committing |
| Conflicting override arguments | Reject duplicate fields specified through both legacy keywords and overrides |
| Permission / quota | Intersect allowed capabilities; deny wins; minimum finite cap. Never resolved by last-write preference |
At dispatch acceptance pin the effective snapshot, Agent revision, policy version and relevant catalog/preset versions. Queued work retains this intent; execution rechecks current revocations and required resources. Retries and resume use the same snapshot, not a newly edited profile. New independent turns resolve again. Snapshot provenance contains references and hashes, never credentials.
Public calls and execution boundaries
Proposed API, not available yet. Extend the existing Python agent() and llm() with agent_id, config, overrides and history selection. Do not create a parallel executor. llm() has no Python/Program/MCP tool loop, including when the selected Agent allows those tools. Preserve explicit web_search=True for provider-native search, subject to the same native-action capability checks; selecting an Agent alone never enables search. Output validation and return types remain unchanged.
from openprogram import Agent
# Explicit history sharing; records stay in the same execution DAG.
agent(prompt, agent_id="reviewer", history="selected", context_nodes=[node_id])
class ExampleAgent(Agent):
method_options = {
'extract': {'tool': True},
'classify': {'tool': True},
}
def extract(self, document):
return agent(document, agent_id="my-agent",
overrides={"memory": {"mode": "off"}},
response_format=Result)
def classify(self, document):
return llm(document,
config=AgentConfig(model="provider:model", memory={"mode": "off"}),
response_format=Label)
_example_agent = ExampleAgent()
extract = _example_agent.extract
classify = _example_agent.classify
| Entry | What it creates | History / continuation |
|---|---|---|
| agent() / llm() | An execution node with selected config; no saved Agent | Same DAG storage, separately filtered model view |
| agent tool without to | Existing durable child task/branch | Preserve start_from=clean/inherit/exact-node semantics |
| agent tool with to | Next turn on the addressed existing branch | Do not change target Agent implicitly; conflicting agent_id is rejected |
| Chat / CLI / scheduler | Existing session/job types with the same resolver | Scheduled jobs reference Agent ID and resolve at each new firing; resume keeps its snapshot |
Bind an immutable resolved view through a context-local scope; reset it in finally, including on exceptions and cancellation. Never mutate the shared Runtime.model or a process-global active Agent. Named selection errors are explicit, not fallback to main. Switching the chat Agent starts a new context by default; keeping history is an explicit choice and marks retained data as already disclosed.
Optional memory: access, retention and ingestion
| Mode | Automatic recall / injection | Memory tools | Background write / pre-compaction extraction |
|---|---|---|---|
| off | No reads | No read/write/reorganize calls | No ingestion from these execution nodes |
| read_only | Only authorized read_spaces | Read/search only | No ingestion from these execution nodes |
| read_write | Only authorized read_spaces | Read/search plus one authorized write_space | Writes subject to writer policy and execution provenance |
| inherit | Resolve to a concrete mode first | Never passed unresolved to tools | Migration only preserves historical effective behavior |
read_spaces is a list of stable references: self, a selected project, or an explicitly selected shared space. write_space is one target and must also be readable. self for a saved Agent resolves to its own namespace; self for an anonymous config is invalid, because no persistent identity exists. An explicit project/shared binding makes anonymous memory use possible without saving an Agent. Enabling a new Agent’s memory defaults to self; no silent copy of the old global store.
- Off does not delete memory, disable session history, or remove user-provided instruction files. Already recalled text in existing messages cannot be “unseen”; start a clean context to exclude it from subsequent requests. Disabling reads also invalidates pending recall responses before they enter a model request.
- Every execution node carries a memory-write eligibility label, space reference and policy epoch. Session-end writers, compaction extraction, source export and scheduled reorganizers must filter out off/read_only nodes; they cannot later ingest them by scanning raw history. Disabling writes blocks unsettled queued writes from that scope and prevents retroactive ingestion on re-enable. Previously committed memory remains. Derived output nodes and summaries carry the most restrictive memory-write eligibility of the context actually included; splitting or switching Agents cannot relabel restricted data as writable. Off propagates a no-write restriction but does not by itself forbid an independently authorized read in a later execution. Manual user-provided text outside recorded provenance is not claimed to be automatically classifiable.
- A background write validates the original execution grant and the current space policy at commit. Policy revocation wins over the pinned configuration; document any external backend operation that cannot be cancelled. Never retry with a broader space.
- Off is a managed-memory policy, not a filesystem sandbox. If generic shell/file tools can read memory files, show that limitation; strict separation requires an enforced environment policy. User-authored instructions and uploaded documents remain inputs, even if they contain personal facts.
- Optional memory backend failure produces a visible degraded-memory state and continues without memory; required=true fails before model execution. Write failure preserves the task result and reports persistence failure separately.
- No write_only mode in the initial contract. Reuse MemoryBackend; backends without enforceable namespace/access support cannot enable scoped memory. Do not simulate isolation by prefixing prompts.
Context, instructions and environment
Clean means no inherited conversation messages, not no system or project policy. Selected history references are validated against the caller’s visibility; DAG membership is not authorization. Keep stored history distinct from the rendered model view. Preserving execution history is the default; this design does not introduce an “incognito” retention guarantee.
| Source | Treatment |
|---|---|
| Runtime/owner policy | Enforced outside the model; cannot be overwritten by Agent prompt |
| User/project and scoped workspace instructions | Use the existing authority and scope rules; show source provenance and conflict diagnostics |
| Agent system_prompt and allowlisted instruction files | Configurable instruction sources; empty prompt clears only its own layer |
| Skills | Load on demand within the allowed set, without copying content into AgentSpec |
| Memory and tool/web results | Contextual data with provenance; never promoted to higher-priority instructions |
Persisted instruction files are explicit path references restricted to the Agent workspace allowlist; snapshot content/hash within existing protected execution storage. Workspace and project cwd remain separate fields. A cwd is not an access boundary. Environment profile availability is validated; incompatible host/sandbox requests fail visibly. Context length uses existing Context Engine limits; the configuration does not introduce a second summarizer or append raw tool results by hand.
Capability scope and authority
Programs, Skills, MCP and provider catalogs own definitions and credentials. Agent policies own references and defaults. Runtime computes requested scope from the selected config, then intersects owner authority, parent execution delegation ceilings, project/environment restrictions, global availability and explicit denies. Agent all means all currently available and authorized entries, not permission to use every installed integration.
- A selected empty list is empty in storage, discovery and invocation. Preserve unresolved references and show Missing. Required MCP services must be both allowed and available; contradictory rules fail validation.
- A session or invocation may replace a preference, but cannot expand an enforced ceiling. If a caller’s narrow scope is a delegation restriction it remains active after agent_id changes. Explain rejected overrides instead of silently claiming they applied.
- Discovery, explicit-name loading, skill loading and actual invocation share one resolved policy. Provider-native web search and other native actions are capability-gated too; tools=[] alone is not a universal network restriction.
- Resolve account/service references through existing credential services. Do not add raw keys to AgentSpec, snapshots, exports or demo examples. Anthropic connections use the official API and legitimately obtained API keys with API account billing.
- Direct Python code already authorized by the host is not sandboxed by an Agent allowlist; tools and nested agentic calls remain checked at their public boundaries.
Detailed capability and picker behavior lives in the linked capability and Programs documents. The resource-governance document remains authoritative for admission, usage, cancellation and quotas; this page only selects existing profiles and exposes effective limits.
Multi-agent composition and selection
Runtime branches, Jobs, messages and attach references are specified in the collaboration contract and architecture diagrams; counts and execution budgets follow resource governance. Saved configurations and runtime branches are separate objects. The collaboration implementation-status section records current execution IDs, query/control entries and completion-follow-up gaps.
Select a saved configuration without assigning a mandatory role. A model-only preset, a style-only preset, a no-memory Agent and a project-memory Agent are equally valid. A config reused in parallel creates distinct runs, not new saved Agents.
| Operation | Contract |
|---|---|
| Independent invocation | No automatic previous-task history; same Agent ID may serve many sessions |
| Delegation | Pass explicit goal/input and filtered context; parent cancellation and budget semantics stay in existing task control |
| Continue existing task | Address an existing run/branch; target Agent remains stable |
| Shared memory | Explicit bindings; concurrent writes use backend version checks and idempotent execution IDs |
| Shared files/browser | Resource ownership and serialization are required for conflicting mutations; Agent names do not isolate resources |
| Automatic choice | Deferred extension: rank existing eligible configs using optional metadata; do not create Agents or widen scopes automatically |
Do not automatically persist config changes, new skills or learned preferences merely because one run succeeded. Durable updates use the existing explicit configuration/skill/memory write mechanisms and preserve provenance. Role orchestration, automatic topology generation and marketplace publishing are outside this scope. Optional Agent/model selection is fully bounded in P6 of the implementation plan, after explicit selection works across all entries.
Management API and atomic persistence
| Operation | Target contract |
|---|---|
| GET /api/agents[/{id}] | Summary/detail DTOs include schema_version and revision; no memory contents or secrets |
| POST /api/agents | Name-only creation; safe explicit new defaults; optional idempotency key; no provider call |
| PATCH /api/agents/{id} | Require expected_revision for new clients; top-level changed fields plus reset_fields; validate whole candidate then compare/write once under a cross-process lock |
| POST /api/agents/resolve | Proposed read-only preview for saved or draft config plus invocation context; no session creation, memory search or credentials in response |
| POST /api/agents/{id}/duplicate | Configuration-only by default; new ID/revision, self maps to new empty namespace; shared bindings shown explicitly |
| POST /api/agents/{id}/default | Single authoritative default pointer, atomically updated; profile.default is a derived presentation value |
| DELETE /api/agents/{id} | Reject default or active references with 409; show exact affected resources before user confirmation; use recoverable deletion intent before destructive cleanup |
Keep updated_at for display and the temporary legacy-client adapter only; compare legacy timestamps under the same writer lock and then use the derived revision. New clients use expected_revision. Missing both preconditions returns 428; stale revision 409; invalid schema 400; forbidden scope 403; unknown ID 404. Unavailable execution dependency is a typed preflight error, not a profile fallback. Save an unavailable reference as a draft with readiness warnings; starting it is blocked when that reference is required. Unknown schema versions fail closed without rewriting the file.
Filesystem-backed configuration keeps one canonical agent.json and atomic replacement. A small recovery journal covers create/default/delete operations that touch the index and multiple resources; do not describe multiple os.replace calls as a transaction. On startup reconcile unfinished intents before serving writes. Never delete shared memory, global credentials or arbitrary external workspace paths when deleting an Agent. Existing sessions/DAG references must be enumerated via their actual store, not assumed to live entirely below the Agent directory.
Lifecycle, export and failure behavior
- Creating an anonymous AgentConfig causes no new sidebar entry, workspace or memory folder. Persisting it is an explicit separate action. Saved creation initializes config only; optional instruction files are created on explicit request or legacy compatibility bootstrap.
- Duplicate creates a new config identity with no sessions, learned memory, schedules or credentials. Shared-space references remain references and must be visible in the duplicate preview. Copying instruction-file contents is optional and separate from copying references.
- Export contains portable configuration and optional user-selected instruction text. Exclude memory, history, machine paths, credentials and automatic schedules. Import validates schema, resolves capability references, previews permissions and starts no execution.
- Deleting a non-default idle Agent requires enumerating owned versus referenced resources. Private memory can be retained or explicitly deleted; shared memory is never deleted by this action. Tombstoned IDs cannot accept new runs; unfinished cleanup is visible and retryable.
- A failed preflight produces no provider request or tool side effect. A failed save preserves the complete draft. Provider failure follows existing bounded retries without silently changing model or policy. Cancelled execution restores scoped runtime state and does not convert to success.
- Policy edits affect new executions; immediate deny/revocation takes effect at the next access boundary for active executions. A memory write disable also invalidates unsettled writes. Show the distinction in the UI; do not imply all active inference can be recalled.
Reference corpus and design choices
| Reference | Adopt / adapt | Boundary |
|---|---|---|
| Meta Muse — official system description | Persistent work and policy enforcement outside the acting model | No claim that OpenProgram has Muse VM isolation; persistent memory/persona remain optional |
| Grok Bot — Bot management / overview | Saved configurations, separate conversations, explicit shared resources | Do not require a specialized job; do not duplicate schedules or learned memory |
| OpenClaw — configuration / CLI / workspace / runtime | Preserve per-Agent workspace and policy references | Workspace is not a sandbox; no new profile inheritance graph |
| Claude Code — CLI reference | Separate model/instruction/tool/session choices | Reference only; Anthropic integration remains official API-key based |
| Codex — configuration reference | Separate config, provider and MCP responsibilities | No claim of identical profile or approval semantics |
References describe product or configuration concepts, not proof of internal implementation. Official unversioned pages may change; the capability statements above are the comparison boundary. Research novelty, benchmark wins and autonomous routing are not claimed.
Observable acceptance contract
| ID | Public entry | Expected observation |
|---|---|---|
| A01 | Agent API / UI | Name-only Agent can run a general task without role or memory; no mandatory specialist fields |
| A02 | PATCH from two clients | Exactly one same-revision update wins; no mixed model/tools config or partial save |
| A03 | agent(), llm(), chat, dispatch | Same base and authorized overrides yield equivalent effective config; llm has no Program/MCP tool loop; native search remains explicit and authorized |
| A04 | Parallel nested functions | Different models/memory policies do not leak across calls; scope resets after failure/cancel |
| A05 | All memory ingress + egress | Off/read-only executions never become learned memory through later ingestion or compaction |
| A06 | Switch Agent / selected history | No implicit prior-task history; inaccessible DAG nodes rejected |
| A07 | Capability discovery and invoke | Empty stays empty; missing references stay visible; denied action never executes |
| A08 | Queue / retry / resume | Pinned revision retained; newly revoked capability cannot execute |
| A09 | Duplicate / export / delete | No accidental memory, credential, schedule or shared-resource copy/deletion |
| A10 | Agents page, narrow view, keyboard | All sections reachable; no page overflow; dirty/error/conflict/degraded states visible |
| A11 | Legacy profile migration | Existing effective model, capability scope, memory behavior and stored history preserved |
| A12 | Default App / CLI / scheduler | Shared resolver evidence; default App only, no extra development profile |
Detailed scenario inputs, files, stage gates and implementation order are owned by the implementation-plan document. A passing static documentation check does not satisfy these runtime acceptance criteria.
Saved specialist Agents
Decision, Lightweight helper and Coordinator are ordinary saved Agents. An explicit installation operation creates missing records through the existing manager under its configuration lock. It preserves existing IDs, edits and the default Agent. Reading the registry does not create records; deleting an Agent does not trigger automatic recreation. There is no template catalog or template selector.
All three are fixed parameter configurations of the existing Agent class, resolved through AgentSpec and Agent.from_spec. They do not add role system prompts. Tasks and scoped instructions come from the call site and Context; an empty saved prompt does not erase ambient instructions. Decision selects exactly one supplied option with Agent.choose: a single tool-free llm request using the existing choice resolver, without a role prompt, advisory response or automatic re-pick. It returns the selected option ID and rejects an invalid answer. The entry retains the current Context and DAG scope. Decision and small-task Agents disable tools; Coordinator can inspect evidence and delegate authorized tasks. Models remain editable; local installation assigns available configured models explicitly. Roles do not guarantee cost or output quality.
Page layout
The page has two areas: a saved-Agent list and a full-width editor. The secondary navigation uses the shared ManagePage split layout and sidebar width token, without Agents-specific desktop width overrides. The detail header contains the name, ID and conversation actions. Seven horizontal tabs remain horizontal at every width, with scrolling when needed. General contains only name, purpose, model and reasoning parameters. Optional manually supplied instructions remain editable in Advanced, preserving their existing draft and invocation behavior. There is no inner navigation column, duplicate introduction or settings summary. Inputs use normal weight; field labels use medium weight. The existing application font, neutral surfaces, control dimensions and blue selection color provide a consistent visual system. All configuration panels fill the available editor width inside the standard page padding; there is no fixed maximum content width. The editor scrolls independently and the save footer remains visible. Narrow screens replace the Agent list with a select and stack identity fields. Saved invalid reasoning choices remain visible without announcing an untouched baseline as a new error.
Acceptance
Three saved records are visible and editable, no template choice remains, repeated installation preserves user edits, and Agent.from_spec executes a saved record. Existing draft, conflict, duplication and conversation flows remain functional. The compact save footer reports draft state; inherited incompatible settings do not produce a pre-edit form error. Verify desktop and narrow layouts through the real React page and the installed default App.
Specialist saved Agents pass independent specification and quality reviews. The consolidated General editor and horizontal configuration tabs are implemented in source. Delivery records retain their review and verification evidence. Public registry preservation, Agent.from_spec execution, model selection, draft/conflict flows and responsive keyboard navigation pass checks. Installed App acceptance is recorded separately.
Implementation status
The production Agents page uses seven sections, a shared draft, catalog-based model selection, save-conflict comparison and existing animated icons. Persistence includes description, revision, atomic conditional saves, and a memory policy that defaults new configurations to off while retaining legacy shared read/write access. Web conversations use saved Agents; independent trials persist a read-only-or-off session snapshot. Missing required MCP servers fail before a model request.
Memory policy applies to execution, background extraction, derived results and recovery entries, with policy-epoch revalidation before commits. The available spaces are self and legacy_global. See Configure an Agent for product instructions.
Full schema 2 migration, transactional multi-file lifecycle writes, the unified Python AgentConfig API, resolver parity across every entry, arbitrary shared-space catalogs, effective-config preview, an embedded trial panel, portable import/export and automatic Agent/model selection remain target designs. The Web implementation does not establish acceptance of the complete plan. Delivery records retain exact commits, test commands and installation evidence.