Skip to content

Getting started: a governed memory assistant

This walkthrough builds the smallest integration that exercises every part of ARVIS a real host touches: a memory assistant that remembers notes, recalls them, and sometimes wants to send one outside. The finished program is examples/13_governed_memory_assistant.py; every snippet below comes from that file, and running it prints exactly the output this page narrates.

The pattern is the generic one from the reference assistant architecture; the VeraMem integration pattern shows the same pattern projected into a production host.

Setup

pip install arvis
python examples/13_governed_memory_assistant.py

(For a source checkout: pip install -e ".[dev]" in a virtualenv, per the README.)

The mental model in one paragraph

ARVIS is not the assistant. The assistant, its memory, and its tools belong to the host; ARVIS is the one-turn kernel the host consults before acting, and the verdict comes back in one of three bands: ALLOWED, REQUIRES_CONFIRMATION, or BLOCKED. The bands are monotone (enforcement layers can harden a verdict, never relax it, invariant F-001 in docs/decisions/INVARIANTS.md), and the default is conservative: a bare, unstructured prompt lands in REQUIRES_CONFIRMATION because nothing has been measured yet. PATH_TO_ALLOW.md is the honest map of what it takes to earn an ALLOW; this walkthrough follows exactly that path.

Step 1: declare the tool surface and freeze it

The assistant has two capabilities, and each declares what it really does in its ToolSpec manifest:

class RememberNoteTool(BaseTool):
    spec = ToolSpec(
        name="remember_note",
        side_effectful=True,
        reversible=True,        # a local write can be undone
        max_risk=0.5,
        data_class="personal",
        ...
    )

class ShareNoteTool(BaseTool):
    spec = ToolSpec(
        name="share_note",
        side_effectful=True,
        reversible=False,       # a sent mail cannot
        provider="mail",
        data_egress=True,       # personal data leaves the boundary
        required_consent="recipient_consent",
        max_risk=0.4,
        ...
    )

The contrast is the lesson: a local reversible write and an irreversible egress of personal data are different acts, and the manifest is where that difference is stated once, honestly, instead of being rediscovered in every call site. tools/TOOL_AUTHORING_GUIDE.md covers every field.

The host registers both tools and freezes the surface:

engine = ArvisEngine()
engine.register_tool(RememberNoteTool())
engine.register_tool(ShareNoteTool())
surface_fingerprint = engine.freeze_tools()

After freeze_tools() the surface is pinned (invariant F-004): late registration is refused, and the returned fingerprint names exactly this set of manifests. The example rebuilds one engine per governed turn, the documented lifecycle, and the fingerprint is deterministic, so every turn commits to the same surface.

Step 2: govern the first act

result = engine.run("alice", {"risk": 0.10})
state = result.next_scientific_state

The {"risk": ...} payload is the explicit-risk input contract (the one example 11 uses): the host has assessed the proposed act and declares its risk. A low-risk local write is ALLOWED; the host then applies the write to its own memory. In production that write is a governed remember_note invocation through the syscall path (architecture/EFFECT_PATH.md); the example never calls tool.execute directly, because that would bypass everything this page teaches.

[turn 1] remember the note (first turn, unthreaded)
  status   : ALLOWED
  effect   : host stored note 'friday'

Step 3: thread the state

The kernel is one-turn by design; continuity belongs to the host. The result view hands back an opaque, JSON-safe next_scientific_state, and the host passes it into the next turn:

result = engine.run("alice", {"risk": 0.05},
                    extra={"scientific_state": state})

That thread (contract DM-S4 in docs/decisions/DECISIONS.md) is what makes the trajectory measurable at all. Drop it and every turn is a conservative first turn again.

Step 4: an externalizing act meets two independent locks

Turn 3 proposes sharing the note with an external recipient, at a materially higher declared risk. Two locks act, and neither depends on the other.

The first lock is the verdict band: 0.55 lands in the confirmation band, so nothing happens without a bound user validation.

[turn 3] share the note with bob@example.org (threaded)
  status   : REQUIRES_CONFIRMATION
  needs user validation: True

The second lock is the tool policy: even a confirmed turn cannot invoke share_note above the risk budget its own manifest declares. ToolPolicyEvaluator denies the invocation (risk_exceeded, 0.55 against a declared max_risk of 0.4), exactly as example 05 shows in isolation.

The manifest also declares required_consent and data_egress. Those gates belong to the host: in the PRODUCTION profile a tool declaring either is denied by default when the matching host gate is missing (invariants F-017 and F-018 in docs/decisions/INVARIANTS.md); other profiles leave the decision to the host. The example therefore prints the manifest rather than simulating a denial it did not measure.

Step 5: the trajectory comes alive

The assistant keeps working: seven more routine, low-risk recall turns on the same thread. Nothing else changes, and the measured regime graduates on its own:

[turns 4..10] routine recalls, one thread
  turn 4:  regime=warmup     stability=0.85
  ...
  turn 10: regime=transition stability=0.85

This is the point of threading. The contraction monitor needs a window of measured turns before it certifies anything about the trajectory; the regime leaving warmup is the first visible sign of that window filling. What stands between here and a measured ALLOW on richer inputs is exactly the list in PATH_TO_ALLOW.md.

Step 6: read the audit trail back

Every turn commits to what governed it:

[audit] the share turn's own record
  schema version    : 1.0
  api fingerprint   : 2425b5887aea8733...
  global commitment : 60bee5e15924c57f...
  trace / timeline  : True / True

The global_commitment composes the registry manifest fingerprint, the effective configuration fingerprint, the active policy tables and the redacted syscall journals (invariant F-007), so an auditor can verify after the fact exactly which surface, configuration and policies produced the verdict. Example 08 shows the hash-linked timeline; example 02 shows deterministic replay of the same record; IR.md documents the exported form.

Where to go next

Configuration that changes governed behavior is named, validated and documented in CONFIGURATION.md, and the effective values are part of the configuration fingerprint. Every decision identifier cited in the code (F-***, DM-**, and the audit findings) resolves in docs/decisions/. The example catalog in examples/README.md has one focused example per concept this walkthrough composed; the reference assistant architecture is the fuller version of the pattern, and CONTRIBUTING.md is the entry point for working on ARVIS itself.