Deterministic Agent Watches
Explicitly approved, bounded monitoring with version-pinned evaluators, live reauthorization, immutable evidence, and exactly-once notification intent.
- Activation
- Explicit owner or manager approval
- Decision
- Version-pinned evaluator over fresh authorized data
- Bound
- Three active watches; no more than 24 hours
Agent watches monitor a supported condition for a bounded period. An agent may propose a watch, but it cannot activate one or decide whether the condition is true.
Four outcomes
satisfiedClose the watch and commit exactly one notification intent.
terminal_unsatisfiedClose without presenting a false success signal.
pendingKeep the watch active and schedule its next evaluation.
unavailableMake no truth claim; retry inside the approved window.
Expiry performs one final authorized evaluation. A condition satisfied exactly at the deadline still notifies.
Supported evaluators
agent.session.state@v1watches the owning session for one of the registered states.workflow.run.status@v1watches one same-tenant run for one of the requested statuses.
Evaluator key and version are an exact pair. Upgrading server code does not rewrite
existing watches; a temporarily missing pinned evaluator yields unavailable.
Bounds and authority
- cadence: 1, 5, 15, or 60 minutes;
- window: 30 minutes, or 1, 2, 6, 12, or 24 hours;
- maximum: 3 active watches per tenant, actor, and session;
- at least one notification action is required;
- only session owners/managers may propose, approve, inspect, list, or cancel;
agent_watchesentitlement and live target access are checked at proposal, approval, every tick, and delivery.
Scoped chat tokens cannot delegate watch management. Identical active conditions collapse to one watch. Revoked access cancels before target data is read, and revoked notification authority suppresses a queued delivery with an auditable receipt.
HTTP operations
Every call uses normal authentication plus Ductor-Agent-Protocol-Version: 1:
| Operation | Path |
|---|---|
| Propose | POST /api/v1/chat/sessions/{sessionID}/watches/proposals |
| Approve | POST /api/v1/chat/sessions/{sessionID}/watches/proposals/{proposalID}/approve |
| List | GET /api/v1/chat/sessions/{sessionID}/watches |
| Inspect | GET /api/v1/chat/sessions/{sessionID}/watches/{watchID} |
| Cancel | POST /api/v1/chat/sessions/{sessionID}/watches/{watchID}/cancel |
The MCP-backed propose_agent_watch tool can only propose. Activation remains an
explicit authenticated session API decision.
Durability and notifications
Approval and cap enforcement use a serializable transaction. Due workers use fenced, skip-locked leases; a stale worker cannot commit a decision. Watch transition, immutable evaluation, and notification outbox insert are atomic. Delivery retries reuse a deterministic transaction id.
in_app uses the governed notification dispatcher. Optional wake_session emits a
content-free best-effort wake only after durable notification work succeeds; clients
reread the ledger. Evidence contains hashes, reason codes, timestamps, verification,
and freshness—not model reasoning.
The model explains; it never decides
A model may phrase the proposal or explain a completed result. Replay, truth, state transition, and notification authority never depend on an LLM call.
Operations
Apply migration 480 before enabling durable chat. Repeated unavailable commonly
means source storage failure, missing evaluator registration, or stale/unverified
evidence. Never repair watch rows manually; restore the dependency or cancel through
the API.
Trusted-Edge Admission
Signed, expiring, replay-safe anti-abuse context for AI-chat admission without trusting browser metadata or proxy topology.
Inference Proxy
Ductor's provider-neutral inference vertical — unary and internal streaming paths, routing, circuit breakers, tenant budgets, usage, and provider credentials.