veritas-kanban

Agent Providers

Veritas works as a board without any agent runner. When you do enable agents, provider profiles are configured in Settings -> Agents and are stored in the same app config for the web app and the macOS desktop app.

Agent provider settings

Defaults

Fresh v6 installs use OpenAI Codex as the default agent:

Existing configs keep the user’s chosen default agent. Missing built-in profiles are added during config normalization without overwriting customized commands, arguments, or enabled states.

Claude Code v2.1.218

The first-class claude-code adapter contract is pinned to Claude Code v2.1.218. Veritas launches the executable directly in the assigned worktree with no shell and a reproducible system-owned argument set:

claude --bare --print --output-format stream-json --verbose \
  --include-partial-messages --include-hook-events \
  --forward-subagent-text --permission-mode dontAsk

The public Claude Code repository does not contain the complete CLI implementation. This contract is therefore pinned to the v2.1.218 release, official CLI/headless documentation, and checked-in golden stream fixtures; unknown versions invalidate conformance instead of inheriting certification.

The exact launch also disables slash commands and Chrome, caps turns at 100 by default, applies an optional run cost budget, and derives allowed and denied tools from the effective sandbox. Read, Glob, and Grep are available in all sandboxes. Edit and Write require a writable sandbox. Bash requires both a writable sandbox and network access. WebFetch and WebSearch are denied when network access is disabled, and sensitive environment, secret, and credential file patterns are denied. Caller arguments cannot replace these controls, inherit settings/plugins/MCP configuration, select an unrelated session, or bypass permissions. Veritas may append system-owned --resume <session-id> and --fork-session only after the provider-neutral lifecycle validator binds the exact source attempt.

--bare deliberately skips Claude Code’s local settings, plugins, MCP servers, OAuth, and keychain state. Veritas therefore copies the worktree’s AGENTS.md into the attributed task request and requires explicit bare-mode authentication. Supported credential keys are ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_FOUNDRY_API_KEY, ANTHROPIC_FOUNDRY_AUTH_TOKEN, AWS_BEARER_TOKEN_BEDROCK, and the bounded AWS credential set used for Bedrock. Vertex requires an explicit GOOGLE_APPLICATION_CREDENTIALS file reference. Vertex, Bedrock, and Foundry selectors are allowlisted separately but do not prove authentication on their own. Claude Code’s subprocess environment scrubbing is forced on so Bash, hooks, and MCP subprocesses cannot inherit provider credentials. Arbitrary custom headers, config directories, and unrelated credential-shaped environment variables are not forwarded.

Readiness runs bounded claude --version, claude auth status, and claude agents --json probes without a shell. The auth status probe is useful diagnostic evidence, but only the explicit bare-mode environment satisfies launch authentication. The runtime profile requires an exact 2.1.218 (Claude Code) version match and probe revision 16; version or build drift invalidates conformance evidence.

Claude’s stream is consumed as bounded JSONL. Partial text/thinking, tool use/results, hooks, subagents, retries, usage/cost, and terminal results map to the shared causal event journal. The provider session_id is stored separately from turn identity in run-event/v1 and on the attempt as its continuation handle. Veritas waits for queued stdout processing and parses the final unterminated record after process close, preventing the terminal result from being lost during stream drain. A successful process exit without an authoritative successful result record fails closed.

Resume and follow-up use the exact persisted session_id; fork combines --resume with --fork-session so the source history is not mutated. Interactive approvals, elicitation, steering, compaction, and archival remain explicitly unsupported. Run-scoped MCP injection is supported through a Veritas-generated --strict-mcp-config document and an exact --allowedTools list. Only tools with an allow catalog decision are exposed to Claude; approval-required tools remain available only through the Veritas-mediated tool-call surface.

Credential-gated release smoke is opt-in:

VERITAS_CLAUDE_CODE_SMOKE=1 pnpm --filter @veritas-kanban/server exec vitest run \
  src/__tests__/claude-code-provider.smoke.test.ts

The smoke requires the exact certified executable and explicit bare-mode authentication. It runs one read-only, network-disabled, one-turn request with a $0.25 provider cap and verifies the authoritative result record. The normal test suite skips it.

OpenAI Codex app-server v0.145.0

Veritas supports three distinct Codex execution roles:

The app-server adapter is pinned to codex-cli 0.145.0, upstream tag rust-v0.145.0, commit 25af12f7e61572b0bc18ddb1008be543b91519b0. Its checked-in schemas were generated by that exact executable. The certified generated schema-set digest is b59f4df6df8d00b3e665b533416efcfef9b5530bcd22a1e4a15dfe7bbd3a8624. Version or build drift invalidates conformance evidence at provider probe revision 12.

Veritas owns the launch:

codex app-server --stdio --strict-config \
  -c mcp_servers={} -c hooks={} \
  --disable plugins --disable apps \
  --disable in_app_browser --disable computer_use \
  --disable tool_call_mcp_elicitation

The process starts without a shell in the assigned task worktree. The safe Codex environment preserves the normal authentication context and operator allowlist while forcing CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1. Live certification requires the app-server to report remote-control status disabled.

The outbound method allowlist contains initialize, thread start/resume/fork/compact/archive, and turn start/steer/interrupt. Veritas initializes once, binds one task attempt to an exact thread and active turn, persists thread/turn/item identity, validates every consumed request, response, notification, and provider request, and maps streamed items, usage, file changes, and authoritative turn/completed into the causal run journal and completion contract. JSONL records are capped at 4 MiB. Uncorrelated or schema-invalid records fail closed. Documented overload error -32001 receives bounded exponential backoff.

The upstream thread/shellCommand method runs unsandboxed and is structurally unreachable from Veritas. Command, file-change, permission, legacy exec/patch, tool-question, and MCP elicitation requests enter the durable run-approval/v1 broker. The exact action is hashed, the provider waits for one authenticated compare-and-set decision, and the adapter sends a response validated against the pinned method-specific schema. Rejection, expiry, interruption, cancellation, stale evidence, and response errors fail closed. Only tool questions are marked mobile-safe by this adapter; shell, filesystem, network, permission, and MCP requests require a non-mobile reviewer.

Resume, follow-up, steer, fork, compact, archive, close, and crash reattachment are capability-gated against the immutable runtime evidence. Native history forks retain the parent conversation and optional source-turn boundary without mutating the source. Inherited MCP servers, plugins, apps, hooks, browser/computer tools, and remote control remain disabled. When a profile selects MCP definitions, Veritas passes only the immutable run catalog as thread-scoped mcp_servers configuration. Approval-required tools are disabled in native configuration and must use the mediated tool-call surface.

Credential-gated release smoke is opt-in:

VERITAS_CODEX_APP_SERVER_SMOKE=1 pnpm --filter @veritas-kanban/server exec vitest run \
  src/__tests__/codex-app-server-provider.smoke.test.ts

The smoke requires the exact authenticated v0.145.0 executable, runs one read-only task-bound turn, verifies the authoritative completion text, and confirms remote control remains disabled. The normal test suite skips it.

ACP stdio agent provider

The acp-stdio provider is the generic stable Agent Client Protocol v1 adapter. Use it for an agent runtime that implements JSON-RPC over newline-delimited stdio. The configured command is the ACP server executable itself; Veritas starts it without a shell in the assigned task worktree.

{
  "type": "my-acp-agent",
  "name": "My ACP Agent",
  "command": "/absolute/path/to/my-acp-agent",
  "args": ["--stdio"],
  "enabled": true,
  "provider": "acp-stdio",
  "model": "provider-owned-model"
}

Before changing attempt state, Veritas starts a bounded probe process and sends ACP initialize with protocol version 1. The returned agent name, version, capabilities, and a deterministic capability digest become provider-runtime-manifest/v1 evidence at probe revision 16. Launch starts a fresh process and rejects capability drift before opening or prompting a session.

Supported mappings:

ACP operation Veritas contract
session/new Fresh conversation-lifecycle/v1 session
session/load or session/resume Exact persisted provider conversation
session/fork Provider-native fork when negotiated
session/prompt Attributed task-envelope turn
session/cancel Cooperative run interruption
session/close Provider close when negotiated
session/update Ordered run-event/v1 journal records
session/request_permission Exact-action run-approval/v1 request

The runtime receives only the standard safe process context, the effective sandbox environment allowlist, and environment keys required by the immutable run tool catalog. Values are never written to manifests or logs. Stderr is bounded and redacted, JSON-RPC records are capped at 1 MiB, pending requests have bounded timeouts, and the supervised process group receives a graceful termination followed by a bounded force-stop.

Run-scoped MCP definitions are translated into ACP session configuration. Native injection is allowed only when every discovered tool on a selected server has an allow decision. ACP v1 cannot express per-tool deny or approval rules, so a partial catalog fails closed instead of exposing extra tools. Credential-bound native server definitions remain omitted. Selected credential-bound tools use the system-owned veritas-run bridge, which binds an opaque in-memory handle to the exact run catalog and consumes one-shot credential leases only inside the mediated downstream call.

Expose Veritas sessions to ACP clients

The inverse ACP server view lets an editor or another ACP client operate one Veritas-managed task without creating a second session store:

vk acp status --json
vk acp serve --stdio --task TASK-001

vk acp status --json reports API reachability, protocol methods, and the authenticated role/workspace context. Individual operations continue through the existing permission guard. vk acp serve --stdio writes protocol records only to stdout. Diagnostics remain on stderr.

The process may bind one task with --task; otherwise session/new must provide _meta["veritas/taskId"]. The client cwd must exactly match the task’s active worktree. A deterministic task-derived ACP session ID maps session/new, session/load, session/resume, session/prompt, and session/cancel onto the existing conversation lifecycle, supervisor, run-event journal, approval broker, and launch evidence. Optional _meta["veritas/afterSequence"] provides cursor replay after reconnect.

The first prompt starts a fresh provider conversation while retaining the immutable task envelope. Later prompts use the attributed follow-up path. Permission requests are relayed to the ACP client and decided through the durable exact-action approval broker. Client-owned MCP server definitions are rejected because Veritas owns the run tool catalog. Closing stdin or disconnecting the client leaves the durable run active; session/cancel interrupts the current conversation and never invokes task stop.

See ACP Provider v1 architecture.

Buzz Agent ACP

buzz-agent is a built-in, disabled-by-default runtime profile under acp-stdio; it is not a new provider type. Veritas tests Buzz release v0.4.24 at commit 710ed9fff57878a1d69f809b80a6ee0416c53fc4 and requires the runtime to identify itself as buzz-agent 0.1.0 during ACP initialize. Identity, version, capability, profile revision, release, and commit evidence are included in the provider build digest and checked again at launch.

The tested profile supports fresh sessions, prompt completion, cancellation, message/tool updates, and stdio MCP. It reports in-memory sessions, no session/load, no HTTP/SSE MCP, and non-streaming LLM calls truthfully. Resume therefore fails closed. buzz-acp is the inverse relay-side ACP client and is never accepted by this profile.

When a run selects tools, the profile receives exactly one system-owned veritas-run stdio MCP descriptor. The opaque handle is bound to the task, attempt, immutable catalog, launch manifest, and lifecycle. Buzz reads the selected catalog and makes allowed or approval-backed calls through that bridge; unrelated or denied tools are absent or rejected. Native MCP definitions, task credential values, the global Veritas MCP inventory, and HTTP/SSE fallback are never injected.

Veritas does not install Buzz or Rust. Build or install buzz-agent, then configure BUZZ_AGENT_PROVIDER plus the matching model and authentication keys. The profile allowlists Buzz configuration and only these boot credential keys: ANTHROPIC_API_KEY, OPENAI_COMPAT_API_KEY, and DATABRICKS_TOKEN. They remain provider-required boot authentication, not task credential brokering. Unrelated Buzz relay and server secrets are excluded.

GitHub Copilot CLI ACP (public preview)

copilot is a built-in, disabled-by-default runtime profile under acp-stdio. The tested runtime is GitHub Copilot CLI v1.0.74, which identifies itself as Copilot 1.0.74 during ACP initialize. The live credential-free handshake advertises session loading, HTTP/SSE MCP, image and embedded-context prompt input, and session listing.

Veritas owns this process-wide stdio baseline:

copilot --acp --stdio --no-auto-update --no-remote --no-remote-export \
  --disable-builtin-mcps --no-custom-instructions --no-ask-user \
  --no-experimental \
  --secret-env-vars=COPILOT_GITHUB_TOKEN,COPILOT_PROVIDER_API_KEY,COPILOT_PROVIDER_BEARER_TOKEN,GH_TOKEN,GITHUB_TOKEN

The profile accepts the agent model plus only bounded restrictive settings for available/excluded tools, denied tools/URLs, reasoning effort, context tier, and maximum AI credits. Broad allow, TCP, remote, plugin/config injection, prompt-mode, and unowned resume flags fail closed before an attempt is created. The same compiled argv is persisted in launch evidence and used for probe and launch.

Authentication remains provider-managed. copilot --version is safe and non-consuming, but GitHub documents no stable non-consuming auth-status command. Run copilot login or configure one of the allowlisted boot credentials. Veritas passes no unrelated credential-shaped variables, and the system-owned --secret-env-vars setting strips those keys from Copilot shell and MCP subprocesses.

ACP support is public preview. The public repository is incomplete, and the v1.0.74 tag currently resolves to commit 2b809c84e87dbcc88f897cb4f3fb97c43b77af95, whose commit message still names v1.0.73 even though the release assets and runtime report 1.0.74. Veritas records that provenance mismatch as a limitation and certifies the exact release/version/handshake contract, not unprovable binary-to-source lineage. Provider-managed COPILOT_HOME is inherited for login state, so the profile also reports that it is not a fully isolated bare configuration.

Grok Build ACP

grok-build is a built-in, disabled-by-default runtime profile under acp-stdio. Veritas tests the released Grok Build v0.2.111 executable, which reports grok 0.2.111 (94172f2aa4e5) [alpha] and advertises agentVersion: 0.2.111 in its ACP initialize metadata. The profile requires session loading, HTTP/SSE MCP, embedded-context input, no ACP image input, and the negotiated x.ai/fs_notify and x.ai/capabilities extensions.

Veritas owns this process baseline:

grok [restrictive global policy] agent --no-leader \
  [--model=<model>] [--reasoning-effort=low|medium|high] stdio

The optional global policy accepts only bounded deny rules, tool allow/removal lists, sandbox selection, and feature-disable flags. Approval bypass, reauthentication, shared-leader attachment, plugin/profile injection, endpoint overrides, prompts, worktree creation, and resume flags fail closed before an attempt is created. Veritas starts a dedicated process in the assigned worktree and owns session creation or loading through ACP.

Authentication is provider-managed. grok --version is the only readiness probe; it does not authenticate or consume inference. Existing login state is read through GROK_HOME, or operators can provide the allowlisted XAI_API_KEY, legacy GROK_CODE_XAI_API_KEY, or GROK_DEPLOYMENT_KEY boot credential. These remain provider authentication, not task credentials.

The exact macOS arm64 release artifact tested on 2026-07-24 has SHA-256 e1fafdfffe14f339460befaf194360e8f90bfd02efe8a4f24cfa1c7aea657ffe. The stable channel currently serves an artifact that self-reports [alpha]. The reported build 94172f2aa4e5 is not present in the public repository, and the current public source snapshot is newer than the release artifact. Veritas records both provenance limits and certifies the exact executable version/build/handshake contract instead of claiming an unprovable source mapping. Other platform artifacts must report the same pinned version/build; the macOS arm64 artifact is the credential-free smoke baseline.

Buzz communication harness

Buzz relay communication is integrated as a buzz communication adapter, not as an AgentProvider. Settings and vk doctor can verify its relay/community identity, NIP-98 signing identity, relay membership, read capabilities, tested release contract, and optional local command versions without sending a message. Task execution through the separately configured buzz-agent ACP profile remains independent of relay delivery and never starts buzz-acp. See Buzz Connection Diagnostics.

An operator can bind one active Buzz channel mapping to one Veritas workflow with a buzz-workflow-trigger/v1 rule. The first supported event is a root message.posted; replies, adapter-originated echoes, disabled rules, and predicate mismatches never launch a run. Each accepted event is journaled before dispatch with the causal key buzz:{community}:{eventId}:{ruleId}. Replays return the existing run, and restart recovery reconciles an accepted journal entry against workflow run context before attempting dispatch again. The provider-neutral workflow.pre-external-trigger runtime hook remains the policy boundary.

Rules and their bounded audit history are available under /api/integrations/communication/adapters/:adapterId/buzz/workflow-triggers and /api/integrations/communication/adapters/:adapterId/buzz/workflow-trigger-audits. Rule creation requires both integration settings write access and execute permission on the destination workflow.

Harness Support Profiles And Tiers

Every configured agent is normalized to a harness-support-profile/v1 contract. The profile records stable profile and adapter IDs, transport, executable and non-mutating authentication probes, version/build invalidation policy, platforms, launch/worktree behavior, environment and credential allowlists, conformance fixture identity, documentation, and remediation. The contract contains credential key names only, never credential values. Credential-like launch arguments are replaced with [REDACTED] before the profile is exposed or hashed, so rotating a secret cannot turn the profile digest into a secret oracle.

Deterministic certification inputs use harness-conformance-suite/v1. The runner resets a seeded fixture before each trial, applies the same scenario across provider/model/profile/policy/sandbox combinations, and emits harness-conformance-result/v1 with assertion, failure-class, pass-rate, variance, latency, token, cost, retry, baseline, and immutable evidence references. Run the credential-free recorded lane with the documented run-harness-conformance.ts command; credential-gated lanes require explicit opt-in. See Harness Conformance v1.

The live status projection uses five tiers:

Tier Meaning
detected The executable is installed, but the profile is disabled or not ready for dispatch.
configured The explicit adapter is enabled and its runtime probe is ready, but current certification evidence is absent.
certified The installed version, build, manifest digest, and probe revision match a passing conformance result.
degraded The adapter exists, but installation, authentication, probe, compatibility, or certification evidence is unhealthy or stale.
unsupported The profile has no executable adapter or does not support the current platform.

Settings -> Agents displays the same tier returned in GET /api/config/harness-compatibility. vk doctor consumes that compatibility record unchanged: an enabled degraded or unsupported profile is a blocking failure, while an enabled configured profile is a warning until certification is current. Reasons and remediation are redacted before leaving the server.

The reviewed builds, capability evidence, source-availability caveats, fixture identity, and tier definitions are documented in Harness Compatibility. The legacy GET /api/config/agent-support endpoint remains available for API compatibility, but new operator surfaces use the matrix response so they cannot drift.

Task start rechecks the normalized profile before attempt state is created. An explicit provider must match the profile’s executable adapter. A display-only Copilot profile, an unsupported provider, or an unknown provider-less profile fails with an actionable 409 and can never fall through to OpenClaw. Recognized credential material in the configured command or launch arguments degrades the profile and blocks dispatch before probing or attempt creation. Put credentials in an allowlisted environment key or a run-scoped brokered credential reference instead.

For backward compatibility, normalization migrates only known provider-less Claude Code, Codex, and Hermes records when both the built-in type and command identity match (claude-code plus claude -> claude-code, codex -> codex-cli, hermes -> hermes-cli). The legacy Claude-only --dangerously-skip-permissions default is removed during that narrow migration. New and custom profiles must set an explicit provider. Command-name inference is not a general adapter-selection mechanism.

Provider Runtime Manifests

Before a task attempt mutates task state, the selected execution adapter emits a provider-runtime-manifest/v1 snapshot. The snapshot records the adapter and protocol version, provider build/version evidence, configured models, probe timestamp and diagnostics, and every known runtime or sandbox capability as supported, advisory, unsupported, or unknown.

Veritas currently has executable task adapters for codex-cli, codex-sdk, codex-app-server, claude-code, hermes-cli, and openclaw. An explicitly configured Copilot, Codex Cloud, Ollama, LM Studio, or custom profile is not silently sent through OpenClaw; task dispatch fails with an actionable 409 until that provider has an execution adapter.

The exact manifest and its sha256: digest are stored on the current attempt, attempt history, optional run trace, and Markdown run log. Provider identity evidence is collected on each launch. CLI/SDK identities come from bounded runtime or installed-package probes, and conformance probes are bounded before launch. An OpenClaw version supplied through the environment remains degraded operator evidence until host registration can verify it. A matching version/build can reuse conformance evidence for up to five minutes; a version change invalidates it and reruns the probe. Failed probes and unknown versions are not positively cached.

Capability states describe behavior that the current adapter actually proves. They do not imply that adjacent roadmap work already exists. For example, provider-neutral controls remain unsupported or unknown for an adapter until the runtime exposes a verified native operation. MCP governance is supported through the system-owned run bridge for Codex CLI, Codex SDK, Codex app-server, Claude Code, and ACP stdio. All-allow native catalogs remain available where the adapter can enforce them; Hermes and OpenClaw fail closed when a selected catalog requires the bridge.

One evaluator maps those capabilities to launch and run controls. Agent starts always require run.start, run.status, run.logs, run.complete, and workspace.worktrees; callers can add requiredRuntimeCapabilities. Profile tools, MCP servers, token/cost/tool budgets, workflow sessions, structured output, and saved artifacts add their own requirements before provider work starts. supported and advisory evidence qualify; unsupported, unknown, missing, failed-probe, invalid-digest, or mismatched active/persisted evidence fails closed with concrete remediation.

The task status API returns a controls set derived from the persisted launch snapshot. Stop, message/steer, completion, token reporting, logs, tool events, and artifact ingestion compare the active and persisted manifest digests before acting. Task Detail, Work view, and shared co-drive messaging disable actions that the manifest does not support and show the evaluator’s reason.

Provider-Neutral Conversation Lifecycle

conversation-lifecycle/v1 is stored on every attempt. It records opaque provider conversation, turn, and item IDs; parent attempt/conversation and fork turn; lifecycle state; and measured context-window utilization. It deliberately does not store process handles, credentials, leases, or other transient authority.

Task adapter Resume/follow-up Native fork In-flight steer Compact/archive
Codex CLI Supported Unsupported Unsupported Unsupported
Codex SDK Supported Unsupported Unsupported Unsupported
Codex app-server Supported Supported Supported Supported
Claude Code Supported Supported Unsupported Unsupported
Hermes Unsupported Unsupported Unsupported Unsupported
OpenClaw task mode Unsupported Unsupported Unsupported Unsupported

Resume requires the exact source worktree. Fork permits a new worktree only when repository and base revision remain compatible. Both operations compare the source and target provider, adapter protocol, model, sandbox, tool, permission, and launch-policy evidence before attempt state is created. Restart-to-resume uses persisted provider identity and the durable supervisor event cursor; it never replays prior effectful prompts.

Lifecycle mutations are available at POST /api/agents/:taskId/conversation/{action} and through vk agent:{action} or the MCP control_agent_conversation tool. Supported actions are resume, follow-up, fork, steer, interrupt, compact, archive, and close. Every accepted action has auth-derived attribution and a causal conversation.* journal event. Unsupported steering fails the capability gate; any recorded-only fallback returns delivered: false. Generic process stdin is not treated as provider delivery.

Workspace checkpoint rewind is deliberately narrower than ordinary conversation fork. POST /api/agents/:taskId/workspace/checkpoints/rewind is preview-first, requires exact critical approval, and is available only for an active Codex app-server attempt whose target checkpoint names an earlier exact turn in the same thread. Operators may resolve an attribution conflict per path with accept, reject, or leave-untouched; the selected paths and canonical decisions are digest-bound through approval, transaction, and recovery. Veritas interrupts the current turn, commits only the approved workspace paths, forks the approved provider history, and records the new live cursor plus its checkpoint anchor. Other adapters, ambiguous or item-level cursors, unresolved non-attribution conflicts, and changed current-state evidence fail closed.

Agents and supervisors can register the same validated manifest with POST /api/agents/register and refresh it through the heartbeat endpoint. Host provider, model, tool.*, and sandbox posture is derived only from those manifests. Legacy free-form registration fields remain visible but are not trusted for runtime requirements. Route and host-preview requests can declare requiredRuntimeCapabilities; supported evidence qualifies, advisory evidence qualifies with a warning, and unsupported, unknown, missing, or failed-probe evidence rejects the candidate. All requirements must be satisfied by one manifest, so capabilities are never composed across providers. Self-registration requires an authenticated agent key/token whose identity matches the registry agent ID; operators with agent:write can register on an agent’s behalf. Unknown request fields and unredacted secret-like evidence are rejected. Only registrations with a current five-minute heartbeat qualify for routing. Provider version/build changes invalidate the readiness cache and force a new conformance probe; active controls continue to use the immutable snapshot persisted for that attempt.

Causal Run Event Journal

Executable adapters own a mapper into the shared run-event/v1 envelope. OpenClaw, Codex CLI, Codex SDK, Codex app-server, Claude Code, and Hermes preserve provider event identity, session/turn/item identity when the provider reports it, provider time, receive time, source, causal links, and a monotonic per-attempt sequence. Known kinds cover run lifecycle, operator and assistant messages, deltas, reasoning, progress, streams, commands, file changes, tools, approvals, artifacts, usage, and errors. A new provider event that Veritas does not understand is retained as a namespaced kind or provider.unknown; it is never silently discarded or assigned semantics that the adapter cannot prove.

The journal is the ordering boundary for provider output. An event is appended and fsynced or committed before legacy Markdown logs, traces, activity, telemetry, budget accounting, completion state, or WebSocket output project from it. Provider event IDs create stable deduplication keys. File mode stores private per-task/per-attempt JSONL under .veritas-kanban/run-events/; SQLite mode uses migration 0018_causal_run_event_journal and a transactional per-attempt sequence. Each attempt is bounded to 50,000 events and file journals to 128 MiB. Payloads are recursively redacted, strings and collections are bounded, and payloads larger than 32 KiB are replaced by explicit dropped metadata before persistence.

Launch previews expose current redacted provider and selected-host dependency circuit posture. run.started, launch-failure, and terminal journal records retain the corresponding run-dependency-circuit-evidence/v1 snapshot; run telemetry carries compact state counts; and normalized completion results add verified harness evidence for both circuit identities. These records contain opaque dependency IDs and policy/state metrics, never endpoint URLs, request bodies, response bodies, or credentials.

The TypeScript contract is in shared/src/types/run-event.types.ts; the portable schema is shared/schemas/run-event-envelope.v1.schema.json. Consumers replay with GET /api/agents/:taskId/attempts/:attemptId/events?afterSequence=<cursor>. WebSocket subscribers send taskId, attemptId, and afterSequence; Veritas attaches the live listener before replay, buffers concurrent events, then delivers one ordered agent:event stream. The older agent:output projection remains for compatible clients. Existing Markdown attempt logs remain readable and are not rewritten by the journal migration.

Task Envelopes And Commit Policy

Every launch also persists a provider-neutral task-envelope/v1 snapshot. It binds the task and attempt identity, objective, background, constraints, acceptance criteria, worktree identity, launch manifest, expected outputs, verification gates, evidence requirements, and allowed side effects to one canonical sha256: digest. The worktree baseline records HEAD plus every dirty file that existed before launch, including its staged index blob and worktree-content SHA-256. Capture retries when HEAD, status, or fingerprints move and fails closed after three unstable attempts, so later completion evidence cannot claim pre-existing changes.

Worktrees created by Veritas also carry a durable worktree-manifest/v1 allocation. Before dispatch, the attempt claims its ownership lease. The task envelope and run launch manifest bind the worktree manifest ID, lease ID, owning attempt, exact resolved base commit, and whether that base came from a successful remote fetch or an explicit stale-local acknowledgement. Legacy worktrees remain readable, but their launch manifests identify the launch HEAD as legacy evidence instead of presenting it as a remotely resolved base.

Commit behavior is explicit instead of implied by a shared prompt:

A one-off commitPolicy start value overrides task.executionPolicy, which overrides the legacy features.agents.autoCommitOnComplete setting. Legacy true maps to required; false or an absent value maps to allowed. Requested filesystem, process, commit, and artifact scopes are intersected with the effective worktree sandbox; ancestor requests such as / are clamped to the assigned worktree and disjoint paths are rejected. The start response, active status response, task attempt/history, and Markdown run log expose the same immutable envelope.

Provider-Owned Transport Rendering

Each executable task adapter renders the provider-neutral envelope into its own immutable provider-task-envelope-transport/v1 request. OpenClaw, Codex CLI, Codex SDK, Codex app-server, Claude Code, and Hermes renderers all include the envelope digest, runtime identity, objective and bounded context, a bounded workspace-baseline summary, explicit commit policy, allowed side effects, expected outputs, verification gates, and completion evidence contract. When reviewed reflection lessons are relevant, every renderer also receives the same bounded Accepted Memory section. Each entry includes its stable reflection ID and source task, run, and event attribution. Harnesses should treat these as human-reviewed supporting guidance and preserve the identifiers when reporting whether a lesson helped or regressed the run. Profile instructions and saved task checkpoints are rendered as separate, attributed sections and are capped at 20,000 characters each. The persisted task envelope retains the complete baseline fingerprints used for later attribution.

The callback posture belongs to the adapter:

Process and stream adapters are explicitly told not to call the Veritas completion endpoint. None of the renderers claims provider-native structured output; Veritas owns validation and completion normalization. The exact rendered request is fingerprinted as instructions.effective-task-request in the run launch manifest, and the provider and adapter must match the envelope before dispatch.

Authoritative Completion Results

Every terminal transport is normalized into one immutable completion-result/v1: supervised process exit, SDK stream, OpenClaw callback, remote-session report, or operator interruption. The result persists on both the current attempt and attempt history with a canonical digest, a claim-derived idempotency key, completion timestamp, and terminal source. Exact duplicate callbacks are safe after persistence or restart. A callback with different content, attempt identity, or provider-runtime digest returns 409 Conflict and cannot replace the first terminal owner. Callback and remote-session terminal sources are accepted only for OpenClaw. CLI process and SDK stream providers reject callback transport even when an attempt ID and manifest digest are known.

Provider summaries, evidence, artifacts, and verification claims are bounded, redacted, and stored as unverified provider evidence. Veritas independently captures Git HEAD, post-launch files and commits, task verification state, local file artifacts, and observable side effects through the replaceable CompletionEvidenceSource port. Unchanged dirty files from the launch baseline are excluded. The launch baseline records commits already reachable from other refs, so switching or fast-forwarding to pre-existing history is not credited to the attempt. Required commits, forbidden commits, missing verification, missing required outputs, and unauthorized side effects downgrade a claimed success to recoverable partial.

Completion status maps to task state as follows:

The legacy bounded { success, summary, error } OpenClaw callback remains accepted and is normalized into the same contract. New callbacks may report the explicit status, blockers, provider evidence, artifacts, verification claims, and a continuation handle. Codex CLI, Codex SDK, Codex app-server, Claude Code, and Hermes still use their native harness-owned terminal paths rather than the callback endpoint. Every current launch also owns a durable run-supervisor/v1 record. The record binds provider and adapter identity, runtime/task/launch digests, worktree fingerprint and lease, budget snapshot, last durable event sequence, host identity, and a process-group or remote-session control handle. The file and SQLite repositories use revision compare-and-set, and an expiring owner/host/process lease permits exactly one recovery supervisor.

After restart, local Codex CLI, Codex app-server, Claude Code, and Hermes runs reattach only when the original PID, process group, start identity, host, and immutable bindings still agree. Projection replay starts strictly after the stored run-event cursor through the durable journal subscription. Startup reconciles any journal gap after that same cursor. A terminal supervisor record carries the exact normalized completion result, so a crash between terminal ownership and task mutation finishes idempotently on startup. Remote sessions are probed only when their adapter declares reattach or resume support. Missing evidence, unreachable sessions, reused PIDs, foreign hosts, legacy in-process state, and binding drift create a typed recovery reason and recommended next action; they never start duplicate work or signal an unverified process. OpenClaw callbacks remain authoritative for task-session completion.

Effective Run Launch Manifests

Every executable task launch also compiles run-launch-manifest/v1 before attempt state is mutated. It references the task envelope instead of copying its task contract, and records the selected provider/model/transport, redacted command and arguments, instruction fingerprints and precedence, environment key names and broker references, profile tools/MCP/permissions/health checks, sandbox/network posture, readiness and any hashed operator override, budget, routing/fallback, workspace trust, compiled phase evidence and source references, and the origin of each effective value. Prompt content, override text, and credential values are never stored in this manifest.

POST /api/agents/:taskId/launch-preview returns the same compiled contract without creating an attempt or dispatching a process. The CLI equivalent is vk launch-preview <task>. Preview applies the same readiness gate as start. A profile restriction that the selected adapter cannot enforce is returned as a concrete blocker, and start rejects it before pending or task attempt state changes. Declaring tool.calls support is not treated as proof that an adapter can enforce a named allowlist.

Phase authority is resolved at the same pre-mutation boundary for task and workflow launches, retries, fallbacks, conversation continuations, compaction controls, and provider handoffs. A descendant intersects the exact parent launch or current transition evidence, so changing providers or omitting an explicit phase cannot widen authority. Explicit phase launches fail closed with typed blockers when the runtime, sandbox, host, or tool policy cannot prove a required dimension. Tool-command and external-action enforcement support is delivered separately in #1033; prompt text is never accepted as enforcement.

Repository-controlled instructions and executable configuration pass through the provider-neutral workspace execution trust gate before Veritas reads repository instructions or creates an attempt. The gate fingerprints the exact task worktree, inventories recognized instructions, hooks, MCP servers, provider overrides, language-server settings, workflows, extensions, skills, and agent definitions, and evaluates them against an actor-attributed operator decision. Executable configuration requires explicit authorization. Model-only instructions may run provisionally only in enforced restricted mode.

The immutable launch manifest records redacted identity and inventory evidence, the effective decision, project maximum, requested capabilities, and restriction checks. Veritas rescans immediately before provider creation; an identity, inventory, or decision change aborts the launch. Repository policy can only narrow operator trust. See Workspace Execution Trust.

Codex app-server and Claude Code inject a positive MCP catalog through their native run-scoped configuration. Other task adapters reject non-empty MCP selections. All adapters continue to reject named-tool restrictions they cannot enforce; prompt text is never accepted as equivalent enforcement. Approval-required MCP tools are withheld from native provider configuration and can be called only through the Veritas-mediated approval path.

Launches can pass parentAttemptId to compare replay, resume, or fork inputs. The comparison ignores attempt IDs, capture/probe timestamps, and other ephemeral metadata while detecting changes to task policy, provider capability posture, model, instructions, sandbox, budget, routing, and profile controls. The manifest, optional parent drift, and governance trace ID are persisted on the attempt and copied into attempt history. Active run controls compare the stored launch digest as well as the provider-runtime digest. Completion packet metadata links both digests, the provider probe revision/version/build, the governance trace, and parent drift result.

Sandbox launch checks resolve every preset rule through the same manifest. Settings dry-runs send the digest of the newest matching manifest registered by a live host; the server resolves that digest rather than trusting a caller-supplied capability object. A missing, expired, unknown, or provider-mismatched digest fails closed. Required presets block on unsupported rules, while advisory presets record warnings and governance evidence.

Workflow agent steps currently execute through the codex-sdk and openclaw workflow adapters. A workflow configured with codex-cli, hermes-cli, or another provider is rejected before probing or launch instead of validating one runtime and executing another. The workflow run persists the manifest and derived controls before provider execution, then gates resume/reattach, tools, MCP, structured output, token usage, and saved output artifacts from that same snapshot. Capability evidence is surface-specific: OpenClaw task manifests do not claim workflow-only follow-up, reattach, or output-artifact behavior, while workflow manifests use the openclaw-workflow-session/v1 protocol evidence. Token telemetry is required only when the effective step budget includes token or cost limits; runtime-, retry-, or fan-out-only budgets do not require it.

Sandbox Policy Presets

Use Settings -> Agents -> Sandbox Policies to manage reusable filesystem, network, environment, and credential controls for agent execution. Built-in presets are immutable; custom presets can be created, edited, disabled, or deleted.

Presets can be assigned to:

The launch path dry-runs the selected preset before starting any executable provider adapter. Required controls fail closed when the provider or execution host cannot support them. Advisory controls continue with warnings and a governance trace. Settings also includes a dry-run panel that shows effective sandbox mode, network access, environment allowlist, unsupported controls, and the trace ID.

Selective network policies for local task and workflow providers start an authenticated, run-scoped loopback gateway before dispatch. Durable launch and gateway evidence records only the injected proxy key names and policy digest; tokens and proxy URLs are never persisted. HTTP, HTTPS CONNECT, and plaintext WebSocket transports use the evaluated DNS address. ALL_PROXY exposes a separate authenticated socks5h listener with the same host, address, approval, and audit policy; encrypted SOCKS tunnels fail closed when method or path inspection would be required. Both listeners stop during terminal cleanup. OpenClaw is provider-managed and cannot receive this local boundary, so a required fine-grained policy blocks its launch.

Operators that require a corporate or audited proxy can set VERITAS_EGRESS_UPSTREAM_PROXY to an HTTP proxy origin. The gateway evaluates the destination first, pins the resolved address, and then opens an upstream CONNECT tunnel to that address. Proxy credentials remain memory-only; durable evidence records only upstreamMode: http-connect.

When a preset enables scoped approvals, an otherwise eligible block creates a durable, exact-action network approval and holds the request at the gateway. Only an approved request proceeds. Explicit host denies and protected address classes are never approval-eligible. Gateway shutdown aborts pending waits. Every final decision also emits a network.egress telemetry record containing the hashed host key, run key, policy digest, protocol, port, decision, reason, and approval ID when present. URLs, query strings, headers, bodies, proxy credentials, and raw paths are excluded from telemetry.

Local ACP, Claude Code, Codex app-server, Codex CLI, and Hermes processes use a version-bound codex sandbox wrapper when its credential-free conformance probe passes. The wrapper enforces the compiled read, write, deny, dotfile, and protected-metadata rules before the provider starts and applies to descendant processes. Codex SDK and remote OpenClaw runs cannot use that outer process wrapper. They satisfy required filesystem policies only when the exact provider runtime manifest proves every active filesystem capability, including descendant inheritance, run-scoped temporary storage, and cleanup. Coarse provider modes such as workspace-write remain advisory.

Workspace and home aliases cannot escape their canonical base. Nested mounts below an allowed root are denied unless explicitly granted or denied, and the mount topology is rechecked before activation. Provider-native local enforcement blocks if Veritas finds an ambiguous nested mount that it cannot add to the native policy. The bounded workspace tree is also scanned before compilation and immediately before activation for pre-existing hard links that alias inaccessible external inodes.

The immutable launch manifest records the backend, versioned capability contract, executable-content digest, provider runtime manifest digest, policy hash, and only hashes of canonical paths. .git, .agents, .codex, and .veritas-kanban remain explicitly read-only directly beneath writable roots, and cannot themselves be selected as writable policy roots. Local wrapper and provider-native runs use supervisor-owned temporary and cache directories; remote native backends must prove their own run-scoped storage and cleanup contract. See Run-scoped filesystem sandbox backends for the enforcement and failure contract.

There is no per-run override for a required filesystem boundary. The overrideReason launch field applies only to task readiness. Intentionally relaxing filesystem enforcement requires an authorized advisory preset, and the effective decision remains recorded in policy and launch governance evidence.

Credential references and environment-style name=value values are redacted from dry-run output and governance traces. Prefer brokered credential presets for workflows that need scoped secrets instead of exposing broad environment passthrough.

Credential definitions are admin-managed at /api/credential-broker. Records contain only source references, public scope, TTL/use policy, approval posture, and canonical digests. The broker issues opaque, hashed run leases bound to the active attempt, immutable launch manifest, and one exact action fingerprint. Secret values are resolved only inside an internal controlled-dispatch callback; there is no public API that returns a value or issues a lease to a provider. Each use or refresh requires a unique operation ID. Only its SHA-256 fingerprint is persisted, and duplicate operations fail closed rather than replaying credential-bearing work. Completion, failure, interruption, cancellation, duplicate terminal delivery, startup reconciliation, and one-minute periodic reconciliation revoke, expire, or block outstanding leases. Manifest declarations and sandbox broker references must match definition IDs exactly.

This core does not make an uncontrolled provider process broker-capable. Credential-bound tool definitions compile only when enabled broker definitions, MCP scopes, source targets, and immutable catalog evidence match. They are omitted from native provider MCP configuration and provider environment passthrough. Mediated calls consume exact-action leases using the server-owned launch-manifest digest and one-shot downstream sessions. The system-owned veritas-run MCP bridge exposes only catalog read and mediated call methods through an opaque, in-memory run handle. Codex CLI/SDK, Codex app-server, Claude Code, and ACP stdio inject it. Hermes and OpenClaw reject credential-bound launches because their certified transports cannot yet enforce the same bridge contract. Model-provider boot authentication and explicit env-passthrough compatibility remain separate, high-risk paths and are never labeled as brokered. See Credential Broker.

New launches persist run-launch-credential-plan/v1 evidence. The plan classifies known provider boot keys, task integration definition IDs, and unknown credential-like environment passthrough; binds the classification to the provider runtime manifest and probe revision; and contains no values. Task integration references report a brokered tool-control-plane boundary only when the exact run catalog covers every reference; uncovered references remain blocked. A provider-native boot key is reported as provider-required authentication, not as credential.broker support.

Agent Profile Packages

Use Settings -> Agents -> Agent Profile Packages or vk profiles to import reusable YAML/JSON packages that sit above provider profiles. Provider profiles still own low-level command, args, and availability. Profile packages add portable launch metadata:

id: docs-reviewer
schemaVersion: agent-profile-package/v1
version: 1.0.0
displayName: Documentation Reviewer
role: Reviews documentation changes for accuracy and release readiness
enabled: true
capabilities: [docs-review, release-notes]
defaultTaskTypes: [docs]
runtime:
  agent: codex
  provider: codex-cli
  model: gpt-5.1
instructions:
  prompt: Check docs against shipped behavior and call out stale roadmap language.
tools:
  allowed: [shell, git]
permissions:
  level: specialist
policy:
  sandboxPresetId: workspace-write-default

Profile launches pass profileId to /api/agents/:taskId/start. Veritas resolves the package runtime against the configured provider profile, applies the package model, sandbox preset, and budget policy, renders bounded package instructions in an attributed provider-transport section, and records the profile ID/version in the task attempt plus an agent_event activity entry.

Budget Policies

Use Settings -> Agents and Settings -> Data & Storage -> Budget Tracking to define workspace defaults, agent defaults, workflow budgets, workflow-agent budgets, and per-run overrides. Budgets can cap tokens, provider-reported cost, tool calls, runtime, retries, and workflow fan-out.

Soft thresholds create budget-policy governance traces and visible warnings. Hard thresholds can pause for review, require approval, downgrade to a configured model, or cancel the run. Completion packets include the final budget decision, usage, threshold events, related trace IDs, and operator override notes when present.

Execution Admission

Every direct task launch, workflow root, and provider-backed workflow step receives a durable admission-reservation/v1 record before Veritas persists an executable attempt or calls a provider adapter. Workflow roots use the explicit workflow-control admission provider and reserve no provider process or memory estimate. Each executable child step uses its resolved provider, selected host, workflow run, step, and root reservation. Reservations account for run slots, process slots, and operator-estimated memory across optional global, workspace, root-task, provider, and host ceilings. Estimated memory is a configured planning value, not a runtime memory prediction. An invariant one-run-per-admission-task policy also prevents concurrent duplicate launches across server processes.

Configure ceilings through PATCH /api/settings/features:

{
  "admission": {
    "global": {
      "concurrentRuns": 8,
      "processSlots": 8,
      "estimatedMemoryMb": 16384
    },
    "providers": {
      "codex-cli": {
        "concurrentRuns": 4
      },
      "workflow-control": {
        "concurrentRuns": 4
      }
    },
    "hosts": {
      "local-process": {
        "processSlots": 6
      }
    },
    "queue": {
      "enabled": true,
      "globalLimit": 1000,
      "workspaceLimit": 100,
      "leaseMs": 30000,
      "retryBackoffMs": 5000,
      "maxRetries": 3,
      "scheduler": {
        "priorityLevels": 4,
        "defaultPriority": 1,
        "agingIntervalMs": 60000,
        "maxAgePromotion": 3,
        "workspaceBurstLimit": 4,
        "evaluationLimit": 32
      }
    }
  }
}

An individual request larger than a ceiling receives a terminal policy denial. Queueable temporary exhaustion persists one bounded admission-queue-entry/v1 record. Direct, profile, conversation, provider-handoff, child-agent, retry, and fallback starts return status: "queued", queueId, the reserved attemptId, retryAfterMs, and redacted limiting scopes. Harnesses must treat that response as accepted work, not as a failed attempt, and must not submit a duplicate start. Workflow roots and provider-backed workflow steps instead persist state: "waiting" in their admission binding while the run and step remain pending. Scheduled workflows retain source: "scheduled"; queue-monitor continuations retain source: "watcher".

The queue uses the versioned admission-queue-scheduler/v1 policy for agent-launch, legacy direct, workflow-root, and workflow-step targets. It ranks the bounded eligible queue snapshot by task priority, configured age promotion, workspace turns, enqueue sequence, and queue identity. After workspaceBurstLimit consecutive selections, compatible work from another workspace receives the next turn. Age promotion is capped at the highest configured priority, and maxAgePromotion must let the lowest priority eventually reach that level. Provider and host limits only determine capacity readiness; they cannot override durable ordering or create a hidden provider queue.

A worker tries ranked entries until it atomically claims both a queue lease and admission capacity. A capacity-blocked entry stays queued while another ready entry may run. The leased entry persists redacted admission-queue-selection/v1 evidence with raw and effective priority, age promotion, workspace turn, readiness, limiting scopes for skipped entries, and conditional start factors. The evidence never promises an exact start time. The worker then reruns provider, sandbox, budget, workspace trust, and launch-manifest checks before any attempt is persisted. Durable supervisor ownership changes the entry to dispatched; after that point only run recovery may restart or finish the work. Abandoned pre-dispatch leases requeue with bounded backoff. Terminal drift, retry exhaustion, and queue overflow fail closed. Queue records retain task, workspace, agent, execution tree, workflow version and revision, retry or fallback sequence, provider, host, immutable runtime and phase digests, and limiting-scope evidence. Workflow targets never retain prompts, workflow context, tool arguments, or credentials. Agent-launch targets retain only bounded provider-neutral inputs required for exact replay, which may include an operator turn or override reason. Queue inspection, telemetry, Operations, and support bundles omit those private inputs. No target retains credentials, process handles, leases, or raw idempotency keys.

Every built-in and custom provider adapter receives provider-admission-evidence/v1 immediately before dispatch. The evidence binds the shared reservation, launch source, queue-dispatch outcome, and exact execution-tree identity to the durable attempt. Missing or inconsistent evidence fails before the adapter is called, so an adapter cannot widen capacity or substitute an external hidden queue.

Active leases renew while the verified run is live; completion, interruption, cancellation, or launch failure releases the reservation idempotently. Workflow retry and fallback attempts release the prior step reservation before queueing or acquiring the replacement. After restart, task runs use their durable supervisor and workflow runs use the exact persisted root and step bindings before reclaiming a reservation. Roots and steps interrupted after durable queue dispatch but before provider execution resume exactly once. Unverified provider work that was already running remains blocked for operator reconciliation. Caller-supplied idempotency values are represented by a stable SHA-256 identity in durable records; the original value is not stored.

Every reservation also carries a versioned execution-tree identity. Resume, follow-up, fork, retry, fallback, provider handoff, workflow-step, and child-agent launches preserve the same root objective and exact parent edge. The capacity claim and strictest applicable workspace, agent, workflow, run, and root-objective budget claim share one atomic repository operation. Idempotent node usage events convert reserved tokens, cost, tool calls, runtime, idle time, retries, and fan-out into committed attribution. Release returns only unused reservation; committed usage remains in the tree.

Inspect reservations with vk admission list, vk admission get <id>, or the matching read-only REST endpoints. Use --workflow-run, --workflow-step, --root-reservation, or --root-objective to follow a tree. Use vk admission tree <root-objective-id> for aggregate totals, remaining policy capacity, blocking policies, bounded contributors, and durable cancellation or circuit-breaker control. Machine consumers should use --json. Inspect the conditional, redacted queue view with vk admission queue list, vk admission queue get <queue-id>, or the matching /api/v1/admission/queue endpoints. Queue position is evidence at the response generation time, never an exact start-time promise. Machine consumers may use the safe navigation identifiers to open related task, attempt, workflow, and execution-tree views without accessing the redacted launch payload.

Operators can stop a queued launch with vk admission queue cancel <queue-id> --reason <text> or cancel an entire execution tree with vk admission cancel-tree <root-objective-id> --reason <text>. Supply --idempotency-key <key> when an automation may retry the request. Tree cancellation is recorded on the root reservation before descendants are drained, so harness-driven resume, retry, fallback, workflow-step, and child-agent launches fail closed before any provider adapter runs. The command reports verified running attempts that the local supervisor could not interrupt; those require explicit operator reconciliation.

Veritas also applies one provider-neutral fan-out circuit breaker before every tree expansion. The default guard pauses a root at 256 descendants, depth 16, 64 active reservations, 64 queued descendants, or 95 percent capacity/budget pressure once the tree has eight descendants. A paused decision includes bounded execution-tree-breaker-evidence/v1 signals and returns EXECUTION_TREE_EXPANSION_PAUSED. Codex, Claude Code, Buzz, Grok Build, GitHub Copilot, Hermes, OpenClaw, and custom harnesses must treat that outcome as a durable stop signal, not transient provider throttling: do not start a local retry storm, change providers, or create a fresh root to evade it.

Inspect the root with vk admission tree <root-objective-id> or Operations. After the reported active, queued, capacity, or budget pressure clears, an administrator can run `vk admission resume-tree --reason

`. Veritas re-evaluates the same durable evidence after restart and rejects unsafe resumes with `EXECUTION_TREE_RESUME_BLOCKED`. A successful resume preserves the breaker history for audit and allows subsequent launches; tree cancellation remains terminal. ## Local And Cloud Profiles | Profile | Provider | Default command | Auth / readiness | | ------------------ | ------------------ | --------------------------------------------- | ------------------------------------------------------------ | | OpenAI Codex | `codex-cli` | `codex exec --sandbox workspace-write --json` | `codex login status` | | OpenAI Codex SDK | `codex-sdk` | `codex` | SDK import plus Codex login | | Codex app-server | `codex-app-server` | `codex app-server --stdio --strict-config` | Exact v0.145.0 plus `codex login status` | | OpenAI Codex Cloud | `codex-cloud` | `gh` | `gh auth status` | | Claude Code | `claude-code` | `claude` | Explicit bare-mode environment auth plus bounded probes | | Hermes Agent | `hermes-cli` | `hermes` | `hermes --version` + `HERMES_API_KEY` or `ANTHROPIC_API_KEY` | | Ollama Local | `ollama-local` | `ollama run llama3.2` | `ollama list` | | Ollama Cloud | `ollama-cloud` | `ollama run gpt-oss:120b-cloud` | `ollama signin` or `OLLAMA_API_KEY` | | LM Studio Local | `lm-studio-local` | `lms server status` | `lms server status --json --quiet` | Ollama local API access does not require authentication on `localhost:11434`; cloud models require either `ollama signin` from the local install or an `OLLAMA_API_KEY`. See the official Ollama authentication docs: <https://docs.ollama.com/api/authentication>. LM Studio local serving is controlled by the `lms` CLI. `lms server start` starts the local API server, and `lms server status --json --quiet` returns machine-readable readiness. See the official LM Studio CLI docs: <https://lmstudio.ai/docs/cli/serve/server-status>. ## Web App Vs macOS App The provider model is the same in both shells: - The web app talks to the Veritas server. Local providers execute on the server host, not on the browser machine. - The macOS app bundles and supervises the local Veritas server. Local providers execute on that Mac. - Cloud profiles are still explicit. Routing a local workflow to a cloud provider surfaces a warning during workflow dry-runs. - Remote or cloud clients should not route directly to local-only providers unless a trusted local host/supervisor is configured. Sandbox policy enforcement follows the execution host: - **Local desktop:** filesystem paths, environment passthrough, credentials, and network controls apply on the user's Mac through the bundled server/provider process. - **Remote server:** the same presets apply on the remote Veritas server host. Browser and mobile clients never receive direct local filesystem access. - **Cloud-hosted runners:** only provider-reported controls can be treated as enforced. Required controls fail closed when the cloud provider cannot prove support; advisory controls continue with traceable warnings. ## Routing Use **Settings -> Agents -> Agent Routing** to change defaults. A route can match task type, priority, project, or subtask count, then choose an agent, model override, and fallback. Recommended starting point: 1. Keep `codex` as the default for general software work. 2. Enable `ollama-local` or `lm-studio-local` for local model experiments where privacy and offline operation matter more than model capability. 3. Enable `ollama-cloud` only when the workflow is allowed to leave local execution. 4. Use explicit routing rules for local LLM profiles instead of making them global defaults on teams with mixed operating systems. ### Automatic retry and fallback `agentRouting.maxRetries` and `agentRouting.fallbackOnFailure` are captured in each new run launch manifest. Task attempts and workflow steps use the same durable `run-recovery/v1` decision record: - Only transient transport, provider unavailable, rate-limit, timeout, and verification failures are automatically retryable. - Invalid configuration and policy blocks require operator action. Explicit cancellation stops recovery. A failed or partial run with destructive side effects requires approval before another launch. - Retry backoff is exponential, capped at 30 seconds, and jittered by 20 percent. The attempt chain retains its root and parent IDs, route, source and launched manifest digests, and cumulative budget. - A fallback is launched only after retry exhaustion and only after its runtime capabilities and sandbox policy pass the normal launch preflight. An incompatible fallback produces an actionable exhausted handoff. - Scheduled task and workflow recovery is reconciled after server restart. Revision claims and terminal idempotency prevent duplicate callbacks from starting multiple branches. Inspect a task decision with `vk agent:recovery --json`. Cancel the exact pending parent with `vk agent:cancel-recovery --attempt `. MCP clients use `cancel_agent_recovery` with the same task and parent attempt. REST clients use `GET /api/agents/:taskId/recovery` and `POST /api/agents/:taskId/recovery/cancel`. --- ## Hermes Agent (v2026.7.7.2) **Provider ID:** `hermes-cli` **Tested version:** Hermes Agent v2026.7.7.2 ### Overview Hermes Agent is dispatched using its non-interactive one-shot scripted interface. Veritas spawns `hermes -z ` in the task worktree without a shell, captures the final response from stdout, and uses the exit code to determine success or failure. Hermes reads `AGENTS.md` from the worktree root automatically. ### Setup 1. Install Hermes via the official distribution channel for your platform. 2. Verify installation: `hermes --version` 3. Set `HERMES_API_KEY` or `ANTHROPIC_API_KEY` in the Veritas server environment. 4. Enable the Hermes provider in **Settings → Agents** and set **Command** to `hermes`. 5. Set **Provider** to `hermes-cli`. ### Environment Only the following keys are forwarded to the Hermes subprocess (plus any keys in the sandbox passthrough list): `ANTHROPIC_API_KEY`, `HERMES_API_KEY`, `HERMES_CONFIG_DIR`, `HOME`, `PATH`, `SHELL`, `TERM`, `TMPDIR`, `USER`, `LANG`, `VK_API_URL`. All other environment variables are filtered out. ### Invocation mode | Mode | Command | Notes | | ------------- | -------------------- | ------------------------------------------------ | | One-shot task | `hermes -z ` | Final response text only; used for task dispatch | | Version probe | `hermes --version` | Used by readiness / health checks | ### Limitations - **Session resume** (`--resume` / `--continue`) is not implemented in this release. Hermes runs are one-shot only. Resume support is tracked for a future iteration. - Stop/cancel sends `SIGTERM` to the subprocess, with a 5-second `SIGKILL` fallback. - OpenClaw-style callback is not used; Veritas receives the final result directly from the Hermes process exit and stdout. ### Troubleshooting | Symptom | Fix | | ------------------------------- | --------------------------------------------------------- | | `Executable "hermes" not found` | Install Hermes and ensure its directory is on `PATH` | | `authenticated: null` in health | Set `HERMES_API_KEY` or `ANTHROPIC_API_KEY` in server env | | Empty stdout on exit 0 | Check `AGENTS.md` is present in the worktree root | | Non-zero exit, no clear error | Inspect stderr in the agent log: `.veritas-kanban/logs/` | --- ## OpenClaw (v2026.6.11) **Provider ID:** `openclaw` **Tested version:** OpenClaw v2026.6.11 ### Overview OpenClaw task and workflow runs are dispatched through the OpenClaw gateway HTTP API using `POST /tools/invoke` with the `sessions_spawn` tool. The spawn acknowledgement is the reachability and policy check: if it fails, Veritas returns an actionable configuration error and rolls the attempt back to `todo` rather than leaving it in a stuck `running` state. Veritas does not issue a separate probe because OpenClaw v2026.6.11 ignores the endpoint's reserved `dryRun` field. ### Required gateway tool policy `sessions_spawn` and `sessions_send` are **blocked by default** in a fresh OpenClaw v2026.6.11 install at the operator-level endpoint. You must explicitly allow them: 1. Add `sessions_spawn` to `gateway.tools.allow` in the OpenClaw configuration. 2. Add `sessions_send` too if workflow session reuse is enabled. 3. Confirm the active agent/tool profile also permits these tools. 4. Save the configuration and restart the gateway. ### Setup 1. Run an OpenClaw v2026.6.11 instance locally or on a reachable host. 2. Configure the gateway tool policy (see above). 3. Set `OPENCLAW_GATEWAY_URL` to the gateway base URL (default: `http://127.0.0.1:18789`). 4. Optionally set `OPENCLAW_GATEWAY_TOKEN` for bearer-authenticated gateways. 5. Enable the OpenClaw provider profile in **Settings → Agents**. ### Environment variables | Variable | Default | Purpose | | -------------------------------- | ------------------------ | ---------------------------------------------------------------------------------------- | | `OPENCLAW_GATEWAY_URL` | `http://127.0.0.1:18789` | Gateway base URL | | `OPENCLAW_GATEWAY_TOKEN` | _(none)_ | Bearer token for the gateway | | `OPENCLAW_GATEWAY_SESSION_KEY` | `main` | Parent session key | | `OPENCLAW_GATEWAY_ALLOW_PRIVATE` | `false` | Allow private IP gateway URLs | | `OPENCLAW_GATEWAY_VERSION` | _(none)_ | Operator-declared version hint; the manifest remains degraded until runtime verification | ### Dispatch flow 1. Veritas calls `sessions_spawn` with the OpenClaw-owned task-envelope transport, including the callback URL and required `attemptId` plus `providerRuntimeManifestDigest` completion provenance. 2. A policy or connection failure rolls the task attempt back to `todo` with an error message. 3. OpenClaw returns a `childSessionKey` which Veritas stores in the attempt record. 4. The OpenClaw sub-session runs autonomously and calls the Veritas callback URL when done. Late or replayed callbacks are rejected when either provenance value differs from the active attempt. ### Limitations - Stop/cancel is not supported for individual sub-sessions in OpenClaw v2026.6.11. A stop request logs a warning but cannot forcibly terminate the sub-session. - Session resume is driven by the callback flow; no explicit `--resume` flag is used. - OpenClaw v2026.6.11 does not accept per-spawn run timeouts. Configure `agents.defaults.subagents.runTimeoutSeconds` in OpenClaw instead. ### Troubleshooting | Symptom | Fix | | ------------------------------------------------------------ | --------------------------------------------------------------------------------------- | | `sessions_spawn is not allowed` on start | Add `sessions_spawn` to `gateway.tools.allow`; add `sessions_send` for workflow reuse | | `OpenClaw gateway did not respond` | Check `OPENCLAW_GATEWAY_URL` and gateway process is running | | Task stuck in `running` after old request files appear | Old request-file artifacts can be safely deleted from `.veritas-kanban/agent-requests/` | | `OpenClaw sessions_spawn did not return a child session key` | Verify the gateway is running OpenClaw v2026.6.11 or later |