Skip to main content

Local-first governance for AI agents — wire it into Claude Code in one command, observe execution against an operator-authored policy, and see where compute and intent diverged.

Project description

sentience-governor

See what your AI agents did, what systems they touched, and where execution diverged from intent — in real time.

Install → run → see your first trace in under 2 minutes.

sentience-governor is the open-tier governance wrapper for AI agents. It intercepts execution at the boundary, observes it against governance primitives and default policy rules, and produces a structured local trace — now with optional per-turn LLM-token attribution so you can correlate execution cost with execution behavior.

It does this without modifying agent behavior, without blocking execution, and without sending anything anywhere automatically.

Status: v0.2.5.5. Apache 2.0 licensed. Runtime + Sentience Sync CLI + live production sync endpoint at https://sync.getsentience.ai/v1. One-command Claude Code setup (sentience init claude-code), operator-defined governance posture via ~/.sentience/profile.yaml, optional per-turn LLM-token attribution on traces, undeclared-intent token spend analyzer, packaged runnable demos. Full test suite (623 tests) + golden-trace coverage + per-commit acceptance gate against live prod.

What's new in 0.2.5.5

Fresh-install adoption. The whole first journey now works without a walkthrough: install → discover commands → wire the hook → capture → inspect/analyze → author the profile.

sentience init claude-code              # wire the Claude Code hook — no hand-edited JSON
sentience                               # bare command now prints a helpful guide
sentience demo undeclared-intent        # a runnable example, works on any install
sentience analyze undeclared-intent --showcase   # populated analysis before token capture is wired

Plus: sentience open accepts a trace file path (not just a session id); --latest orders by session start time so a live session never reorders results; sentience profile init now ships inline-commented YAML you can read standalone; sentience profile edit falls back through $VISUAL/$EDITOR/nano/vim/vi/TextEdit. No schema changes; additive CLI surface only. (0.2.5.2–0.2.5.4 were consumed during TestPyPI validation — see CHANGELOG.)

What was new in 0.2.5

Operator-defined governance posture. v0.2.5 introduces the first durable, operator-authored artifact the runtime evaluates against: the governance profile at ~/.sentience/profile.yaml. One profile, evaluated across every wrapper surface — Claude Code hook, MCP wrapper, LangChain handler. Authored once; travels with the operator.

# Common commands (six verbs total — see the Commands table below for export/import)
sentience profile init       # create your first profile
sentience profile view       # inspect it
sentience profile edit       # tune it ($VISUAL/$EDITOR, else nano/vim/vi, else macOS TextEdit)
sentience profile validate   # schema check (read-only — never mutates the file)

The profile encodes three things the runtime asks of every governed session:

  1. When undeclared intent is surfaced — per-event, first-write-only, or never.
  2. When the agent has crossed a task boundary — directory change, file-type shift, read-to-write transition, or time gap.
  3. Which tools should be treated as high-consequence — operator-authored regex patterns matched against <tool_id>:<target_system>.

All signals are observational; nothing is blocked. Every event in a governed session carries a 12-character profile_fingerprint so traces correlate back to the profile that produced them. Two new advisory flags — TASK_BOUNDARY_CROSSED and HIGH_CONSEQUENCE_DETECTED — fire when a profile match triggers. The sentience analyze undeclared-intent analyzer gains three optional report sections (Profile, High-consequence operations, Task boundaries crossed) that surface in both CLI and Markdown output.

No breaking changes. Sessions that run without a profile produce traces byte-identical to v0.2.4. The profile system is strictly additive: existing v0.2.4 integrations continue to work unchanged.

See userdocs/sentience_governor.md §11 for the full guide and examples/showcase/v025-closed-loop/ for a complete runnable walkthrough — profile, agent recipe, generated trace, generated analyzer report.

What was new in 0.2.4

Undeclared-intent token spend. First derived metric over the v0.2.3 token-attribution substrate. Tells you how much compute was attributed to reasoning turns that touched execution outside the session's declared operational intent.

sentience analyze undeclared-intent --latest

Deterministic analyzer with replay-stable output. Optional Markdown-report save flow. Differentiated copy when no intent was declared anywhere — frames the result as a surface-level limitation (e.g. Claude Code hooks today) rather than agent drift. See userdocs/sentience_governor.md §10 for the full guide and examples/showcase/ for three pre-rendered scenarios.

What was new in 0.2.3

Execution-cost attribution. Token spend now rides directly on execution-boundary traces. Per-turn identity (llm_turn_id) keeps multi-tool-call attribution mathematically correct under aggregation. Optional, all fields default None; non-adopters see zero schema change.

First-run UX. The CLI greets you the first time you run it and offers an optional one-line ask to hear when the hosted console ships. Easy to skip, never re-asks.

LangChain + LangGraph. SentienceCallbackHandler.on_llm_start / on_llm_end callbacks capture per-turn LLM token usage automatically. LangGraph users can register SentienceMiddleware.awrap_step for step-level aggregation.

Simple mental model

Sentience governs at the execution boundary, not after the fact.

Session = one run of an agent Event = one action inside a session Trace = all events in a session


What it does

  • Captures agent tool calls at the execution boundary
  • Emits structured governance events
  • Evaluates each event against five default policy rules
  • Produces local traces you can inspect
  • Shows what paid enforcement would have flagged, without blocking anything

What it does not do

  • Does not block or modify agent execution in the open tier
  • Does not send telemetry, licensing checks, or data automatically
  • Does not persist data across sessions
  • Does not require a Sentience account, API key, or network connection
  • Does not classify data unless classification is provided by the integration

Install

pipx install sentience-governor
sentience --help

That's the install. Two commands. Registers four CLIs on your $PATH: sentience, sentience-cli, sentience-sync, sentience-claude-code-hook.

Verify install:

pipx list

Upgrade:

pipx upgrade sentience-governor

Uninstall:

pipx uninstall sentience-governor

If you don't have pipx: brew install pipx (macOS) or python3 -m pip install --user pipx (Linux/WSL), then pipx ensurepath and restart your shell.

Library integration: if you're importing sentience_governor as a Python module inside your own project (MCP wrapper, LangChain callback, custom agent runtime), use pip install sentience-governor inside your project's virtualenv. The pipx path above is for CLI usage; pip-in-venv is for library usage.

Requires Python 3.10+. No account. No signup. No API key.

Want to know when the hosted console ships? Drop your email at https://getsentience.ai/launch-list — or just install and we'll ask politely on first run. Optional, easy to skip, never re-asks.


Start here: first trace

If you use Claude Code, this is the fastest path.

  1. Install:

    pipx install sentience-governor
    
  2. Add the Claude Code hook config shown in the Quickstart (Claude Code hook) section below.

  3. Run Claude Code normally.

  4. Review the latest trace:

    sentience open --latest --summary
    

You should see:

  • A session listed
  • Events captured
  • A summary explaining what happened

If you see nothing, run:

sentience status
sentience list

Commands

Most used commands

sentience open --latest --summary   # see what happened
sentience list                      # see recent sessions
sentience status                    # confirm the hook is capturing
sentience-sync run                  # optional: upload aggregated counts

Installing the package registers four CLI entry points. Skim this table before reading further; pick the one that matches what you're doing.

Command Use it when… Details
sentience reviewing an agent-hook session trace (Claude Code today; more coming). Curated, signal-first output. sentience status / sentience list / sentience open [--latest | <id>] [--summary]
sentience-cli inspecting a library trace (MCP wrapper / LangChain handler) or a golden-trace fixture. Raw, full-fidelity. sentience-cli <file> / my-agent | sentience-cli
sentience-claude-code-hook invoked by Claude Code via .claude/settings.json. Not run directly by operators. Reads JSON on stdin, emits governance events, exits 0.
sentience-sync opting in to send aggregated rule-fire counts to Sentience Cloud. Manual, explicit, one run at a time — never automatic. Requires --email and --name on first register. sentience-sync init / register --email ... --name ... / run / status / update-check

sentience subcommands (agent-hook viewer):

Subcommand What it does
sentience init claude-code [path] Wire the Claude Code hook into a project's .claude/settings.json (idempotent merge). (v0.2.5.5+)
sentience status Is the hook capturing sessions? Prints the trace path and last session.
sentience list One line per session, newest first, max 20.
sentience open --latest Full curated render of the most recent session (Summary / Focus / Notes / Key Events / Full Trace / Footer).
sentience open --latest --summary Same render, minus the Full Trace block — fits one terminal screen.
sentience open <session_id | path> Render a specific session by id/prefix or a trace file path.
sentience analyze undeclared-intent [--latest | --showcase] Compute how much compute was attributed to turns that touched execution outside the session's declared intent. --showcase runs a bundled example. Add --json for structured output, --save to write a Markdown report. (v0.2.4+)
sentience demo {undeclared-intent,closed-loop} Run a packaged demo session through the analyzer — works on any install. (v0.2.5.5+)
sentience profile {init,view,validate,export,import,edit} Manage the governance profile at ~/.sentience/profile.yaml. init creates a starter (now with inline-commented YAML), view inspects it, validate is a read-only schema check, edit opens an editor ($VISUAL/$EDITOR/nano/vim/vi/TextEdit). (v0.2.5+)

Two-CLI discipline: sentience-cli and sentience exist on purpose. They serve different audiences (library integrators vs agent-hook operators) with different trace shapes (10–50 events vs hundreds).


Quickstart (Claude Code hook)

If you're using Claude Code, one command wires the hook into your project — no hand-edited JSON, no code changes:

sentience init claude-code        # wires the hook into ./.claude/settings.json
# or target a specific project:
sentience init claude-code /path/to/project

This writes (or idempotently merges into) .claude/settings.json with the correct absolute path to the hook binary for your install. It never clobbers existing hooks or settings; re-running is a no-op.

Prefer to wire it by hand?

Drop this into .claude/settings.json (project-local) or ~/.claude/settings.json (user-global). Replace sentience-claude-code-hook with its absolute path if it isn't on Claude Code's $PATH:

{
  "hooks": {
    "PreToolUse": [
      {"matcher": "", "hooks": [{"type": "command", "command": "sentience-claude-code-hook"}]}
    ],
    "PostToolUse": [
      {"matcher": "", "hooks": [{"type": "command", "command": "sentience-claude-code-hook"}]}
    ]
  }
}

Every Claude Code tool call now emits a governance event. Per-session traces land at ~/.sentience/traces/claude-code/<session_id>.jsonl by default. Fail-open, observe-only, no credentials.

Known blind spot: Bash commands are captured at the tool-call boundary but the shell command string itself is not parsed (the hook sees Bash(cmd='...'), not what the shell ultimately resolves).

Review what Claude Code actually did with the curated sentience CLI:

sentience status                    # did the hook fire? yes / no
sentience list                      # what sessions exist
sentience open --latest --summary   # curated view of the latest session, one screen

This is the main first-value path for operators.


Quickstart (MCP client wrapper)

wrap_mcp_client() targets an internal MCPClientLike protocol. To wrap a concrete MCP SDK client, adapt it through SentienceMCPAdapter — the adapter keeps the wrapper free of any SDK-specific method names.

from sentience_governor.cache.cache import InProcessCache
from sentience_governor.session_manager.manager import SessionManager
from sentience_governor.sink.writer import SinkWriter, StdoutSink
from sentience_governor.wrapper.mcp import (
    SentienceMCPAdapter,
    wrap_mcp_client,
)

# Shared per-process collaborators.
session_manager = SessionManager()
cache = InProcessCache()
sink = SinkWriter(StdoutSink())

# Adapt your SDK client to the MCPClientLike protocol.
# `call_fn(delegate, tool_name, arguments) -> dict` is the only SDK-aware bit.
adapted = SentienceMCPAdapter(
    delegate=your_sdk_client,
    call_fn=lambda client, name, args: client.call_tool(name, args),
)

wrapped = wrap_mcp_client(
    target=adapted,
    session_manager=session_manager,
    cache=cache,
    sink_writer=sink,
    agent_id="my-agent",
    agent_version="1.0.0",
    vendor_id="my-company",
    declared_capabilities=["crm.read"],
    owner_claim="user_123",
    stated_objective="Generate Q1 customer report",
)

async with wrapped:
    result = wrapped.send_tool_call("crm.get_customer", {"id": "123"})

Integration consists of three steps: import Sentience, assemble the collaborators, wrap the client.


Quickstart (LangChain-based agent)

Attach SentienceCallbackHandler as a callback. It duck-types the LangChain BaseCallbackHandler interface, so no hard dependency on langchain-core at import time.

from sentience_governor.cache.cache import InProcessCache
from sentience_governor.session_manager.manager import SessionManager
from sentience_governor.sink.writer import SinkWriter, StdoutSink
from sentience_governor.wrapper.langchain_adapter import SentienceCallbackHandler

session_manager = SessionManager()
cache = InProcessCache()
sink = SinkWriter(StdoutSink())

handler = SentienceCallbackHandler(
    agent_id="my-agent",
    session_manager=session_manager,
    cache=cache,
    sink_writer=sink,
    agent_version="1.0.0",
    declared_capabilities=["crm.read"],
    owner_claim="user_123",
)

agent.invoke(
    {"input": "Generate Q1 customer report"},
    config={"callbacks": [handler]},
)

If you are building with create_react_agent and prefer the middleware integration path, SentienceMiddleware wraps the same handler and plugs in via the middleware= keyword. It is observe-only in v0 — it never blocks.

from sentience_governor.wrapper.langchain_adapter import SentienceMiddleware

middleware = SentienceMiddleware(handler)
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt, middleware=[middleware])

Token tracking (optional, v0.2.3+). SentienceCallbackHandler.on_llm_start and on_llm_end capture per-turn LLM token usage from LangChain responses automatically and attach it to subsequent tool-call events with a per-turn llm_turn_id so multi-tool-call attribution stays mathematically correct. LangGraph users can additionally register SentienceMiddleware.awrap_step for step-level aggregation. See userdocs/sentience_governor.md "Token tracking (optional)" for the full integration guide, per-provider cache-token semantics, and the aggregation contract.


Control points

sentience-governor wraps your agent's execution boundary and emits structured governance events at five control points:

  • AGENT_REGISTERED — who is acting
  • INTENT_DECLARED — what they are trying to do
  • SCOPE_ASSERTED — what tool they are calling and why
  • CONTEXT_SNAPSHOT — what data is in their context
  • MEMORY_WRITE_ATTEMPT — what they are trying to persist

A sixth event type, GOVERNANCE_ERROR, is emitted by the runtime itself when an internal fault occurs (sink unavailable, schema violation, intercept failure, timeout). It is always routed to stdout regardless of the configured sink, and never interrupts the agent.


View your trace

For Claude Code sessions:

sentience open --latest --summary

For raw library traces:

sentience-cli path/to/agent.jsonl

Use sentience for high-volume agent-hook sessions. Use sentience-cli for full-fidelity library traces.


Default policy rules

Rule What it checks
POL-001 Agent must declare intent before executing mutating operations
POL-002 Agents must be registered before accessing tools
POL-003 Data entering context must be classified
POL-004 Memory writes must carry classification and retention policy
POL-005 Sensitive data must not escalate in context without explicit authorization

All five rules are evaluated on every session. Violations are surfaced and simulated — never enforced in the open tier.


Sinks

Three sinks are shipped. Pick one at construction time and pass it to SinkWriter.

Sink Use
StdoutSink Default. One JSON object per line to stdout. Pipe into sentience-cli.
FileSink Append newline-delimited JSON to a file path.
HttpLocalSink POST each event as JSON to a local URL. 500 ms timeout, no retry. Loopback only.

Failure semantics are uniform across sinks:

  • Writes are synchronous, unbuffered, and never retried.
  • On failure, the event is dropped and a GOVERNANCE_ERROR is routed to stdout.
  • Severity escalates per session: 1 failure → warning, 3 consecutive → degraded, remainder of the session → critical on close.
  • The agent is never blocked.

Sentience Sync

Optional. Manual. Sends only aggregated counts — never raw events, tool arguments, tool responses, or payloads.

Sentience Sync is the opt-in feedback channel between your installation and Sentience Cloud. It is how both sides learn:

  • For you (the operator): is my policy working? are my agents actually hitting the rules I care about? is my installation running the version I think it is?
  • For Sentience (the maintainer): which policies fire in the wild, at what frequency, across which runtime versions? Signals that inform the next release.

It is completely opt-in. Installing the runtime sends nothing. Wrapping an agent sends nothing. Events land in local trace files on your machine only. Sync transmits anything to Sentience Cloud only when you explicitly run sentience-sync register and then sentience-sync run.

Why it exists

Sync gives operators a lightweight roll-up of policy activity and update notices for their installed runtime version. It also gives maintainers aggregate signal about which rules fire in real deployments.

It never auto-applies updates and never changes runtime behavior.

What Sentience Cloud sees

Every sentience-sync run POST contains only:

  • installation_id
  • runtime_version
  • window_start / window_end
  • counts_by_rule

Sentience Cloud never sees raw event content, agent IDs, user IDs, tool names, arguments, responses, payloads, source code, logs, or business context.

Registration additionally collects email and name because Sync is the update/support channel. organization and operator_role are optional.

Safety

Built for unattended runs. Failure is safe.

  • No state advancement on failed uploads — failed runs retry from the same offset, no data loss.
  • Logs are always the source of truth.
  • Duplicate runs are idempotent (server returns duplicate=true, CLI exits 0).

CLI

sentience-sync init
sentience-sync register --email you@example.com --name "Your Name"
sentience-sync run            # default
sentience-sync status
sentience-sync aggregate
sentience-sync update-check

Exit codes: 0 success · 1 config · 2 network · 3 not registered · 4 server · 5 state.

Config

{
  "endpoint": "https://sync.getsentience.ai/v1",
  "log_sources": ["/var/log/sentience/agent.jsonl"],
  "report_geo": false
}

Precedence: CLI > env > file > defaults.

The default endpoint is live. Use SENTIENCE_SYNC_ENDPOINT or the endpoint field in your config to point at a different target.

Boundary

  • Runtime has zero dependency on Sync — enforced in tests across the codebase.
  • Sync cannot influence execution or policy.
  • Uninstalling Sync (deleting the sentience_sync directory) does not affect the runtime.

Upgrade to enforcement

The open tier answers: what happened. The paid control plane adds enforcement: what should be blocked, narrowed, paused, or escalated.

Real enforcement — block, narrow, scope contraction, pause — and organisational memory across sessions and agents are paid control-plane capabilities.


License

Apache 2.0. See https://www.apache.org/licenses/LICENSE-2.0.

Copyright 2026 Crescere Labs, Inc.


Sentience — Crescere Labs, Inc.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sentience_governor-0.2.5.5.tar.gz (165.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sentience_governor-0.2.5.5-py3-none-any.whl (163.2 kB view details)

Uploaded Python 3

File details

Details for the file sentience_governor-0.2.5.5.tar.gz.

File metadata

  • Download URL: sentience_governor-0.2.5.5.tar.gz
  • Upload date:
  • Size: 165.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for sentience_governor-0.2.5.5.tar.gz
Algorithm Hash digest
SHA256 c92436b6aea8cd5b050d570110ec61cf2b5b6d09415965f91d2ccb58cc15e9bf
MD5 305f9c4a4eb1f96f175d609f4840be7b
BLAKE2b-256 cfd9bf00660bcc3896bd08140d5f7b4fd4fca087d09b508e7fbed8e4a52e6826

See more details on using hashes here.

File details

Details for the file sentience_governor-0.2.5.5-py3-none-any.whl.

File metadata

File hashes

Hashes for sentience_governor-0.2.5.5-py3-none-any.whl
Algorithm Hash digest
SHA256 1df6ce14fc06e8e081d00092976dcb11b6cec3af0382224b6cbe4eb162d2f100
MD5 97ea204558501541c2a2f7da146babc9
BLAKE2b-256 38b3e2ecc6efe43421454dc65cd52251ad45264f214ab9c9f17ead90c565e740

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page