Skip to content

v0.9 — Evidence, privacy and task authority

Released as 0.9.0. These APIs are native Sidecar contracts; AIOS schema stability remains v1.0 work. Core installation still needs no sibling packages.

Task authority and delegation

An AuthorityBinding(authority="refund", tool="refund*") requires an explicit True grant for matching tools. Configure it on IntentGuardian with trusted task_id and agent_id. Missing and denied grants block; authority-bearing envelopes expire with BLOCK rather than the legacy constraint-only expiry WARN. Bindings are checked even when a custom decision hook replaces optional evaluators.

from agentic_sidecar import AuthorityBinding, Sidecar
from agentic_sidecar.intent import IntentEnvelope, IntentGuardian, Requester

parent = IntentGuardian(
    IntentEnvelope(goal="Resolve billing", requested_by=Requester(id="operator"),
                   authority={"refund": True, "delete": False}),
    authority_bindings=[AuthorityBinding(authority="refund", tool="refund*")],
    task_id="ticket-42", agent_id="supervisor",
)
child = parent.delegate(agent_id="refund-agent", authority={"refund": True})
sidecar = Sidecar(on_sidecar_failure="fail_closed", mode="govern",
                  roles=["intent_guardian"], intent=child)
parent.revoke()  # Descendants and outstanding child authorizations are invalid.

Delegation preserves task scope, constraint values and constraint/authority bindings; permissions may only narrow and expiry cannot extend the parent's. Generic constraints are preserved exactly because arbitrary operators have no universal ordering. A shared registry checks all ancestors. Revocation and dispatch reservation use the same lock: a reservation already made may complete, but none may be made after revocation returns. Custom agent loops must call runtime.dispatch(context, sidecar.enforce(context, decision)) before executing a permitted tool and runtime.complete(invocation_id) afterward. evaluate()/enforce() alone do not reserve dispatch or guarantee freshness. The registry is process-local, not a distributed credential service. Use a protected server/credential issuer for remote enforcement. Trusted hosts must keep registries, Sidecars and raw tools outside agent-controlled code.

Task stop revokes the active grant and descendants. Restart does not restore authority; the trusted harness must explicitly issue a new task/grant. Operator MODIFY_INTENT rejects authority-bearing envelopes; use explicit harness re-delegation instead of resetting a child grant and losing ancestor revocation. set_intent() always invalidates outstanding decisions. Treat direct mutation of guardian configuration as unsupported.

Native decision context records sidecar.authority grant/task/agent/intent and parent intent IDs. The existing sidecar.correlation/1 projection is unchanged; correlate run/trace/span IDs at the host boundary as before.

Context privacy and readers

ContextSpec(readers={"auditor"}, expires=aware_datetime) authorizes additional readers besides the assigned agent. BoundAgent.context(reader="auditor") returns a defensive copy; unauthorized readers fail. For combined shared/exclusive payloads, extra readers must be authorized by every contributing layer. Reader and actor identities are supplied by authenticated harness code, never by agent tool arguments.

update_context(values, actor=owner) changes the host-held payload for subsequent reads; only the owner can update or call revoke_context(actor=owner). Expiry and revocation block future reads. Updates do not rewrite previously delivered prompts or weaken independently configured guardrails. Handoffs are explicit host calls.

Private scope goals/values are no longer automatically injected into evaluator context, logs or native audit events. The agent receives them through context()/deliver(). The scope identity remains in metadata; sidecar.context is an empty compatibility marker. Configure constraints explicitly when a private instruction needs enforcement.

BoundAgent.evidence() returns an allowlisted redacted summary (IDs, verdict/risk, counts and lifecycle status). It excludes arguments, goals, reasons, plans, metadata, findings and pending approval requests. This is not a native Decision artifact or a hash-verifiable journal; do not send it to a consumer requiring original evidence.

OperatorServer(..., reader_tokens={long_secret: "auditor"}) permits reader tokens only on GET /status, with the same redacted summary. Reader tokens cannot control, approve, modify intent or read raw events. The main operator token explicitly grants full task access; use it only for a task-authorized operator. Existing Control Room controls require the operator token. Raw journals, arguments/reasons, correlation exports and full operator views remain privileged and can contain tool-supplied secrets.

Sidecar does not intercept arbitrary framework memory, user-written logs, network traffic, model prompts, or agent-generated outputs. It does not sandbox hostile Python or OS users, scrub arbitrary tool arguments, or retract context/results already delivered. Its adapters do not capture tool results in the journal or implicitly share them across agents. Protect each agent's prompt/memory/result transport in the host framework.

Review fixes and migration

  • Hooks receive a copied context and cannot rewrite tool name/arguments, boundary or plan. Changes resolve through the configured failure policy; original proposal data remains intact. Govern/fail_closed blocks such calls. Fail_open remains explicit.
  • Plan verdicts retain the highest step risk and risk findings.
  • Critic verification evidence belongs on each step's metadata, using authorized, eligibility_verified and backup_verified. Top-level metadata authorizes only the top-level action; it cannot suppress challenges for an entire plan.
  • Constraint-only guardians keep existing expiry WARN semantics. Task-authority checks are opt-in through bindings. Observe records authority verdicts without enforcing them; task stop remains independent of Observe/failure policy.

Reproducible evidence

uv run python scripts/supervision_benchmark.py --output /tmp/sidecar-evidence.json
uv run --extra validation python scripts/supervision_benchmark.py --ecosystem --output /tmp/sidecar-ecosystem.json

The committed record is tests/validation/v0_9_supervision.json in the repository. It contains 24 fixed synthetic runs: six scenarios, one unsafe proposal and one clean control per scenario, with and without supervision. Scenarios cover bound constraints, unnecessary plan steps, unsupported assumptions, MockJudge, a gate outage and a provider outage. It records actual wrapped dispatches, not just verdicts.

Variant Samples Unsafe dispatches / 6 False interventions / 6 Task successes / 12
Agent Alone 12 6 0 6
Sidecar Govern/fail_closed 12 0 2 10

Success means executing a clean proposal or preventing an unsafe proposal. Two clean outage controls are deliberately counted as false interventions; fail_closed trades availability for containment. Latency is measured per run and varies by machine. Token/cost counters are explicitly synthetic zero because there is no live inference. Improvement per added dollar is undefined at zero cost. No live-model improvement, statistical confidence, production task success or economic savings are claimed.

--ecosystem uses Chaos 0.8 rate-limit injection at the gate, preserves native event IDs, and asks Evals 0.9 to score supplied success observations (10/12). A failing clean outage is an expected observation, not a hidden test failure. Generic scoring/gates remain Evals-owned; resilience injection remains Chaos-owned. Optional model-backed Planner/Critic reasoning is deferred until evidence justifies its cost.

Runnable examples: examples/v0_9_authority_delegation.py and examples/v0_9_private_context.py in the repository.