Open Agent Toolkit

Providers

Provider Quick Browse

  • Project: .agents/skills -> .claude/skills, .agents/agents -> .claude/agents, .agents/rules -> .claude/rules
  • User: ~/.agents/skills -> ~/.claude/skills, ~/.agents/agents -> ~/.claude/agents
  • Rule files stay .md and are rendered with Claude-compatible frontmatter when needed
  • Managed phase implementers and optional nested workers use the exact configured candidate returned as providers.claude.dispatchArgs.model; OAT passes that value as the actual Agent model
  • Claude's official subagent contract says existing agent directories are watched and changes load within seconds. It describes a conditional restart for the first agent added to a directory that was absent when the session started, for agents added through --add-dir, and when Claude starts with --disable-slash-commands. OAT cannot observe those session-start and launch-mode facts. After a successful provider-visible file change, the generic OAT repository policy therefore conservatively advises starting a new provider session; it does not claim that Claude hot-reloaded the file or that the application process must restart. The provider semantics were verified against Claude Code subagent documentation on 2026-08-31.

Managed dispatch views

Reusable ordered candidate ladders live in workflow.dispatchCeiling.providers. The project or phase named ceiling is only a maximum over those candidates; it does not select one permanent model family for the project.

Adopt the complete ladder into an explicit owning config scope before sync:

oat config adopt dispatch-matrix --shared
oat config adopt dispatch-matrix --local
oat config adopt dispatch-matrix --user

Project-config candidates materialize into the tracked, version-controlled project .codex and .cursor views. User-config candidates materialize under ~/.codex and ~/.cursor. OAT does not auto-ignore project output or create its Git commit; the team owns that repository change.

At implementation time, the root passes the recorded named maximum through invocation-only --ceiling-tier, resolves one exact candidate per phase, and dispatches one phase implementer. Codex first attempts the resolver-returned materialized role as the native agent_type. The launcher records the target, model axis, and effort axis from that resolved payload; child self-report is not provenance and cannot replace those values. Only an explicit pre-start native role-selection rejection permits another target-preserving route. An accepted child, including one that later returns BLOCKED or lacks telemetry, is a task outcome rather than a fallback signal. Claude binds the exact model argument described above. Cursor launches the exact native variant. A missing or unselectable managed target blocks rather than falling back to the root target or a base role.

Post-launch runtime observation

Runtime observation is a separate, optional layer from the configured invocation above. It never changes launch, fallback, policy, ceiling, role, authority, or any selector: it only records what a provider said about its own child, so a configured selection and an observed identity stay independently readable.

Codex reports child lineage, role, model, and effort through its session and turn metadata. It reports no service tier: the parser accepts one for forward compatibility, but no captured rollout carries the field. Claude reports role, model, effort, and service tier from its on-disk transcript metadata, and lineage only as root-or-child: it emits no depth field, so a subagent turn is recorded as depth-unknown rather than given an invented depth. Claude's role comes from the same class of bounded role identifier Codex records, and is reported only on the subagent turns that carry one. Cursor exposes no metadata channel and stays explicitly not-reported.

not-exposed is reserved for an axis a provider genuinely does not have. It is not a stand-in for an axis that simply went unreported on a given run, and it is never written in place of a value the provider did report.

Observation is metadata-only. Parsers select entries by type and never read conversation content, and raw provider output is projected through the owning parser's allowlist before validation, so instruction text, conversation bodies, and working directories are dropped rather than merely ignored. A missing, unparseable, or uncorrelated observation is not-reported, never a copy of the requested arguments or the materialized pin. An observed mismatch is evidence for a human to read; it is not a fallback trigger and cannot authorize replacement or retry.

Materialization, refresh, and visibility

OAT reports three separate facts rather than collapsing them into “available”:

  1. Materialization says whether the canonical asset's provider output was changed, current, missing, failed, unsupported, or unknown.
  2. Catalog refresh policy is provider- and content-specific. A policy is live, manual-refresh, restart-required, or unknown, with its source and verification date.
  3. Runtime visibility says whether the active provider catalog was actually observed. oat sync, oat status, oat doctor, and install-triggered sync do not query a running provider session, so they report visibility as not-reported or unknown, never visible.

After a successful provider-visible file change, oat sync conservatively advises starting a new provider session so the provider has an opportunity to load the changed asset. This repository decision was approved on 2026-08-31 and is recorded in the active project's implementation record. It is safety guidance, not a provider hot-reload guarantee, an instruction to restart the application process, or proof that the new session loaded or exposed the asset. The compatibility schema reports this session boundary as restart-required; with repository-decision provenance, that state means “start a new provider session,” not “restart the application.” No advice is emitted for current/no-op, planned-only, failed, missing, inactive, or unsupported materialization.

A truthful provider/content-specific policy takes precedence over this generic repository decision. Claude's documented behavior remains conditional on session-start and launch-mode facts that OAT cannot observe, so OAT does not claim those conditions were met; the conservative new-session advice still applies after a successful file change. Unsupported capabilities retain an unknown policy rather than inheriting advice. A current file with no current-session catalog probe is still not proof of provider visibility.

Scope rules

  • Project scope: skills + agents + rules
  • User scope: skills plus capability-supported ordinary agents (provider mappings vary by adapter)
  • The two bundled managed roles separately participate in Codex and Cursor extension expansion for user-owned targets
  • Rules are project-scoped only in this release
  • Codex user-scope sync materializes user-config custom roles under ~/.codex; project-config and supported-catalogue output remains project-scoped and version controlled
  • Cursor user-scope sync materializes user-config variants under ~/.cursor/agents; project-config and supported-catalogue output remains project-scoped and version controlled

Adoption model

  • Stray adoption is available in oat init and oat status.
  • Adoption reconciles canonical plus the adopted provider first.
  • Native-read Cursor skill adoption moves the provider-local skill into .agents/skills without recreating a .cursor/skills view or manifest entry.
  • Choosing Keep Cursor-only leaves the skill in place and records its exact normalized path in the project or user sync config.
  • Native-read Copilot skill adoption moves a legacy provider-local skill into the matching canonical .agents/skills directory without recreating a .github/skills or ~/.copilot/skills view or manifest entry.
  • Choosing Keep Copilot-only leaves the skill in place and records its exact normalized path in the project or user sync config.
  • Rule adoption normalizes provider filenames back to canonical .agents/rules/*.md entries before cross-provider fanout.
  • Cross-provider fanout is explicit via oat sync --scope all.

Provider mutation safety

The generic sync engine validates provider destinations for every operation that creates or updates a symlink, creates or updates a copy, or removes a managed provider path. The same guard applies across provider adapters; it is not Claude-specific.

Validation runs at three boundaries:

  1. During planning, before a provider operation is classified.
  2. Across the complete mutating plan before apply starts, so an already-unsafe later entry cannot allow earlier provider or manifest mutations.
  3. Immediately before each entry's first filesystem mutation, so ancestry that changes after preflight fails closed.

A mutation is refused when its destination escapes the sync scope, equals the scope root, or has any existing parent that is a symbolic link or not a directory. The final managed destination is excluded from the ancestry walk, so an existing managed symlink can still be updated or removed normally.

Whole-plan preflight refusal leaves provider paths, canonical content, external symlink targets, and manifest state unchanged. If ancestry changes after preflight, the affected entry fails before its first removal or write and does not gain manifest ownership. OAT does not traverse, unlink, or rewrite the unsafe parent.

Reference artifacts

  • .oat/projects/<scope>/<project>/spec.md (FR5)
  • packages/cli/src/providers/**
  • packages/cli/src/providers/shared/adapter.utils.ts

On this page