Limitations
Circinus is deliberately not:
- a SaaS product or a hosted control plane
- an identity system — no SSO, no SCIM, no RBAC
- a SIEM or a log-shipping pipeline
- a Kubernetes-deployed service
- a runtime for every agent framework — Claude Code only, today
- a global threat-intelligence network
- a custom-trained model or a model-training effort
- a proprietary policy DSL
- a dashboard or a web UI
- a replacement for OPA, Cedar, or existing prompt-guard libraries
Where an established tool already solves a piece of this well, Circinus should compose with it rather than reimplement it.
And concretely, right now, in this build
Shadow mode is fully functional, and it's what every install gets. The
daemon can run in enforce mode — it resolves its live mode from the
install manifest's mode field, so real blocking is technically reachable —
but no shipped command ever writes anything other than shadow into that
manifest. circinus install always writes mode: "shadow"; there is no
circinus config set mode or equivalent. The only way to reach enforce
today is hand-editing the install manifest's JSON file directly, which is
unsupported, untested as a user-facing workflow, and not something any
command guides you through or warns you about. Even then, only one rule
(high_risk_argument_resolves_to_relevant_artifact_without_instruct) ever
actually sets a BLOCK verdict — every other rung of the decision ladder
(wait-budget expiry, adverse semantic evidence, provider failure) is
NOT_ENFORCED regardless of mode in this build.
Bash and fs_write (Write/Edit) are gated end to end; WebFetch is notThe Claude Code adapter recognizes several tool names for observation, and
the synchronous PreToolUse enforcement gate is wired end to end for Bash
calls and, as of MVP 2.1, for Write/Edit calls too — enforced as one
fs_write action class, gated on file_path only (file content is never
read for authority purposes). WebFetch calls are matched and their results
are ingested for provenance, but WebFetch does not yet pass through the
same gate.
COVERAGE_DEGRADED revocation is background-only, not synchronousGrant revocation (GRANT_REVOKED) is synchronous and immediate — a matching
decision fails right away. COVERAGE_DEGRADED, the trigger fired when a
grant's provenance coverage degrades, is the one other named revocation
trigger, but it only propagates through bounded background re-evaluation; it
has no synchronous "matching fails immediately" path. It is deliberately
non-load-bearing for the enforced verdict: the rung-1 authority computation
and enforce_rule.evaluate never take coverage as an input. It can still
affect a shadow-reported verdict (the existing unknown-coverage-to-review
escalation), which is a distinct, unrelated code path. This is a disclosed
scope boundary, not an oversight — see ADR-0016 for the underlying
provenance-coverage contract.
Circinus does not expose any mcp__* tools. Where an agent session uses MCP
tools from other servers, Circinus treats an MCP tool call's result the
same way it treats any other untrusted input — the same bucket as a fetched
web page — not as a privileged or trusted source.
src/circinus/policy/profiles.py defines four named profiles — realtime,
balanced, strict, critical — each with its own wait-budget and
fail-closed behavior (see Architecture). balanced is
hardcoded as the default and there is no user-facing way to select a
different one in this build; the profile mechanism exists in code, but
switching it is not yet exposed.
- Shadow mode is what every install gets, and no shipped command changes that. Enforcement is designed to be opt-in, per-decision-class, and reversible — see the enforce-mode note above for what actually reaching it would take in this specific build, and for the one rule that's the entire enforcement surface even then.
- It is an MVP (
v0.0.0), not production security software. It does not claim prompt-injection immunity: inferred provenance resolution catches literal reuse of an artifact's content in a later argument, and misses transformed reuse — re-encoding, splitting, base64, paraphrase, and homoglyphs all evade it. That is a floor, not a guarantee. - It does not claim enterprise readiness, support for agent frameworks beyond Claude Code, or proven product-market fit.
- There is no published package on PyPI or any other registry — the only
supported way to run Circinus today is from a source checkout with
uv.
Kill criteria
This is an experiment with a stated way to lose. The standalone thesis is parked if either holds:
- no external user reaches a real pilot or willingness-to-pay conversation, or
- native platform features or existing open-source tools already solve more than 80% of the pain.
If either fires, the capability folds back into AI Agent Assembly rather than continuing as a separate product.