Skip to main content

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​

Enforce mode has no supported way to turn it on

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 not

The 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 synchronous

Grant 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 has no MCP server or MCP tools of its own

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.

One fixed policy profile ships today

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.