NXP/Stira-powered agent harness built on Strands Agents SDK.
English | 日本語
An original agent runtime that extends Strands with identity persistence, memory coherence detection, and circuit-breaker safety — the core of the NXP (Narrative Experience Protocol) framework.
"Emotion" here means a numeric state model used for agent state and safety control. It does not claim subjective feelings or consciousness.
Want this in your AI agent? Hand it this repository's URL and say "install this" — it should read docs/agent-setup.md and ask you before running each command. That is the house style here. (Draft wording.)
StiraCore is an alpha. It runs, but parts of it are unfinished and some things do not work
yet. Known gaps on current main:
- No stability promise. This is
0.1.0a1: the Python API, configuration keys, event and file formats and the data directory layout (.local/stira/) can change between commits, without migration code (CHANGELOG). - Local, single-user servers. The web apps have no login. They listen on loopback and
refuse other addresses unless
STIRA_ALLOW_REMOTE=1; one data directory takes one server (security model, operations §1). - Goal grants (autonomy) are experimental and off by default. Amazon Bedrock only, no
prompt caching inside an iteration, cost estimated from one supervised run only, and
run_checksinside a grant only on macOS (known limits). - Exec-class tools (
shell,batch,cron,graph,swarm,think,use_agent) are hidden by default and have no sandbox or background execution yet. Even withSTIRA_ENABLE_EXEC_TOOLS=1they are registered only when the installedstrands-agents-toolsis a release the exec bridge was audited against — today 0.8.9 only.pyproject.tomltherefore holdsstrands-agents-toolsbelow 0.8.10 (>=0.8.0,<0.8.10), so a fresh install gets 0.8.9; this pin is a deliberate safety choice until a newer release is audited. An older or a manually upgraded release is refused for the exec class (the log saysNot registering shell: …). Check withpython -m pip show strands-agents-tools. - Emotion classification is basic. With the default install the stimulus classifier is the
rule-based one: its patterns are English and it detects almost nothing in Japanese. The
Japanese Sokudan classifier needs the
jevextra on Python 3.11 (stimulus classifiers, Japanese rule classifier, opt-in). There is no stimulus category for failure, frustration or pressure yet. - Long one-sided conversations saturate the Neural State: stability runs towards 0 and the breaker sits at CRITICAL, which restricts write tools, for most turns. This is by design; the settings that shape it are in neural-saturation.
- Memory page: a read-only list of the newest 20 entries per layer, text only — no search,
no editing, no importance or retention shown. Procedural proposals are reviewed on that page;
semantic staging only on the command line (
stira_ctl.sh staging). - Other UI gaps: scheduler jobs are created through the API only (
/scheduleslists, pauses, resumes and cancels them — guide); one conversation at a time, with no session list, switch or search; the Stage polls (up to 5–10 s behind when idle), shows one approval at a time and does not show heartbeat ticks or scheduler runs (Stage limits). distiller_mode: "jev"is a stub: every episode fails. Userule(the default, no model call) orllm(memory maintenance).- Platforms. Developed on macOS (Apple Silicon). The CI workflow runs the offline test suite
on Ubuntu (Python 3.11 and 3.12) for every pull request and on macOS (3.11) for pushes to main and manual runs
— both blocking. Windows is best effort, outside CI and outside the guarantee: the code
is written to run there and fixes are welcome, but nothing tests it automatically (its pytest steps were informational
only, several hundred tests still failed: path semantics, the scheduler, grants progress, timing; Issue #662) and it is
checked by hand only when the maintainer has a Windows machine at hand. Treat Windows as not a verified
platform. Beyond CI, Linux was checked by hand only in a VM for the
EC2 reference setup (its AWS parts unverified), and Windows not at all
(
stira_ctl.ps1, the chat server; noshellorcrontool there). The YOLO window is offered on macOS and Linux (the platforms whose clocks were measured, ADR 0012 §7; Windows and virtual machines that pause are not), and the per-OS tool table is from source inspection, not an OS test run (install §4, §6, §11). - Model providers. Amazon Bedrock (the default) is the provider of every real-model run
documented here. The other Strands providers (Ollama, llama.cpp, OpenAI, Anthropic, Gemini, …)
are wired through
ModelSpecand covered by offline contract tests with a fake model, but none has a documented real-model run yet; the opt-in live smoke checks yours (providers).
Found something that does not work, or a gap that is not listed? Please open an Issue in this repository.
Captured on 2026-10-26 from a running build of main (fresh data directory, default tool rules,
Amazon Bedrock); the Stage art in them is CC BY 4.0 (License).
🚧 Early development (0.1.0a1) — APIs and integration points may still change.
The CI matrix needs no cloud account: Ubuntu (Python 3.11 / 3.12) and macOS (Python 3.11). Built on:
- Strands SDK (agent/tool/model abstraction)
- Stira (collapse detection + circuit breaker), an earlier OpenClaw adapter and a decision router prototype — earlier work by the same author, not published
What is implemented today is listed under Features; planned work that does not exist yet is listed under Roadmap.
┌──────────────────────────────────────────────────────────────┐
│ StiraCore Agent │
├──────────────────────────────────────────────────────────────┤
│ NXP Memory Layer │
│ ├── Episodic / Semantic / Procedural (Markdown + SQLite) │
│ ├── AmygdalaPass importance routing (discard/auto/staging) │
│ └── Harvest distillation + staging review queue │
├──────────────────────────────────────────────────────────────┤
│ Stira Engine │
│ ├── NeuralState (6-dim state, lazy decay) │
│ ├── Circuit Breaker (NORMAL/WARNING/CRITICAL/COHERENCE) │
│ ├── bcScore (behavioral coherence) │
│ └── HITL approvals bound to args + operation ledger │
├──────────────────────────────────────────────────────────────┤
│ Context, protection & classification │
│ ├── ContextAssembler (SOUL + anchors + memory + state) │
│ ├── IdentityGuard + SOUL read-only + protected_dirs │
│ ├── SOUL compaction guard (turn-boundary re-injection) │
│ └── Stimulus classifiers (rule / Sokudan) │
├──────────────────────────────────────────────────────────────┤
│ Strands Agent Core │
│ ├── NXPAgent pre/post-turn lifecycle │
│ ├── Providers: ModelSpec / create_model (Bedrock default) │
│ └── Tool registry (exec-class tools hidden by default) │
├──────────────────────────────────────────────────────────────┤
│ Observability & UI │
│ ├── Versioned turn events (SQLite, replay, SSE) │
│ └── Flask apps: chat server + observation console │
└──────────────────────────────────────────────────────────────┘
NXPAgent runs each turn as pre_turn() → tool filtering and context → Strands
call → stimulus classification and post_turn(). Callers do not invoke
pre_turn() / post_turn() themselves. See docs/architecture.md
and the diagrams.
| Concept | What it does |
|---|---|
| Neural State | 6 parameters (trust, curiosity, vigilance, attachment, stability, satisfaction) that act as regularization — preventing optimization from deleting personality. Baselines and decay rates live in core/neural_state.py |
| Circuit Breaker | Defaults: stability < 0.5 → WARNING (write tools withheld, identity injected); < 0.3 → CRITICAL (read-only by default; with critical_action="halt" the model still runs and every write/exec call needs a human approval). Hysteresis (WARNING exits above 0.6) and a cooldown (CRITICAL exits above 0.45 after at least 3 protected turns). All thresholds are configurable in StiraConfig |
| bcScore | Behavioral coherence score over a rolling stability window; a low score raises the separate COHERENCE level. Formula, window and initial-fill behaviour: docs/coherence.md (compute_bc_score) |
| 3-Layer Memory | Episodic (daily) → Semantic (distilled) → Procedural (skills). Markdown files are the source of truth; SQLite is a rebuildable search index |
| Amygdala Pass | Deterministic importance scoring on the write side, on the original turn text: < 0.4 discard, ≥ 0.7 staging for human review; 0.4–0.7 is staged too by default (harvest_stage_auto, until the review UI #193) and auto-promoted only when that is turned off |
| Identity Anchors | Layer 3+ constraints that optimization must never touch. "The things you must not delete for efficiency" |
| SOUL read-only | SOUL.md / IPD.md (and configured paths) cannot be modified by the agent at any breaker level |
| Lazy Decay | Time-based return to baseline that models forgetting. Keeps the system from over-fitting to recent events |
The built-in anchors are three neutral statements with no persona in them
(stiracore.core.DEFAULT_IDENTITY_ANCHORS). A deployment sets its own in
agent-config.json (chat server: .local/stira/agent-config.json, read at start-up):
{"identity_anchors": ["First anchor", "Second anchor"]}Only the keys you write are changed; the others keep their defaults. An
identity_anchors list that is already in your agent-config.json always wins over the
built-in one, so an existing configuration keeps its anchors; an install without the key
switches to the neutral list (one-time start-up warning identity_anchors_default; how to
keep the old list: configuration.md). The
anchors are prompt text: they declare, they do not enforce (the write floor does). A persona-specific example:
examples/personas/resolver/agent-config.json.
In code: StiraConfig(identity_anchors=[...]). The list must be non-empty; the start-up
banner shows Identity anchors: default (3), configured (N) or configured (3, same as built-in).
Everything below exists on main. "Opt-in" means it is off unless you enable or
wire it yourself; a minimal NXPAgent(...) does not start every component.
StiraEngine/NeuralState/StiraConfigwork without any model or credentials (quickstart); decay is path-independent and resyncs on clock reversal.- Circuit breaker with four levels (NORMAL / WARNING / CRITICAL / COHERENCE), hysteresis and CRITICAL cooldown (ADR 0002, state machine).
- Identity Anchors (injected into the prompt by
ContextAssemblerand at WARNING) andStiraEngine.check_layer_boundary()for callers (protected_layers, default L3–L5). MemoryStore: three agent-scoped layers in Markdown with an SQLite index, plus Strands toolsmemory_read/memory_write/memory_search/memory_list(tools may write only the episodic layer) (ADR 0003).- Harvest distillation (
python -m stiracore.control.distillation_cli, orstira_ctl.sh distill): rule-based by default (no model call), optional LLM distiller on any provider; ≥ 0.7 entries (and, by default, 0.4–0.7) go tosemantic/staging/and are approved or rejected withpython -m stiracore.control.staging_cli/stira_ctl.sh stagingor theStagingReviewlibrary API (rejections are remembered). StatePersistence(atomic JSON),ContextAssembler(token-budgeted system prompt),NXPSessionManager, local checkpoints with at-least-once replay (checkpoints).- SOUL compaction guard: re-injects the trusted system prompt and current state at turn boundaries (soul-compaction).
- Opt-in components:
HeartbeatGateway(model-free decay/breaker tick with adaptive pacing;stira_serverruns it in the background only withhb_enabledorSTIRA_HEARTBEAT=1, off by default — heartbeat-daemon),SycophancyMonitormiddleware, isolated NXP subagents and official Strands delegation adapters (harness-components).
- Tool rules Always / Ask / Never per tool and the effective gate stack rule → breaker →
floor (strictest wins), shown on
/settings#sec-tools; the rules file is integrity-checked and locks (every tool Never) when it does not check out (#190, ADR 0010). - Durable, hash-chained approval store: a pending approval survives a restart and approving it resumes the paused tool batch; an unreadable or tampered store rejects everything (#240, ADR 0006).
editoris the SDKfile_editorbehind Stira's write sandbox (#245, ADR 0004); write-failure permission cards andstira doctor(#244, diagnostics).- Opt-in scheduler (
STIRA_SCHEDULER=1, off by default): human-created jobs only, read-only tools, missed-run/overlap/budget/breaker rules, health notifications; on the chat server the model-freehealth_checkaction andmemory_harvest(rule-only Harvest to staging; #251) (#239, scheduler). - Alpha, off by default: goal grants (ADR 0011 stage C, #296) — a person-issued, time-, budget- and scope-limited grant for one goal, iterations in a dedicated session by a press or (opt-in twice) the heartbeat, a permit at every effect, completion verified by the person (Autonomy, autonomy).
- Prompt cache, phase 1: static/volatile prompt split and Bedrock cache points for Claude models, cache usage and prefix fingerprints in turn events (#254, prompt-cache).
- Context management: large tool results offloaded to a durable, masked stash with a read-back tool, summarization at a utilization threshold (#258, ADR 0005).
RuleBasedClassifier: dependency-free heuristics (its patterns are English; it detects almost nothing in Japanese — measured in an internal live probe).SokudanClassifier(Jev-compatible, Japanese,GeneLab/sokudan-ja-310m,jevextra, Python 3.11): runs on CPU without torch; measured p50 ≈ 22 ms on an Apple M1 Max.get_classifier()falls back to rules when Sokudan is not installed.
ModelSpec/create_modelcover the 12 Strands providers: Bedrock (default), Anthropic, OpenAI, OpenAI Responses, Ollama, llama.cpp, Gemini, LiteLLM, Mistral, Writer, Llama API, SageMaker (providers).- Nothing in the harness requires AWS; the test suite runs offline with a fake Strands
model, and a root
conftest.pyguard fails any test that would call AWS. - Credentials by reference: configuration stores environment-variable names only.
- Capability table (
capabilities_for) and provider-neutral usage normalisation; an unknown cost is reported as unknown, never$0. - Secret-free connection test and next-turn model switching from the settings page.
- Opt-in live smoke:
pytest tests/test_provider_live.py -m livewithSTIRA_LIVE_MODEL.
- Versioned turn events (
turn_id, tool calls, approvals, summary) stored in SQLite, replay API (/api/turns,/api/turns/<id>/events) and SSEui_eventstreaming. - Hash-chained
SQLiteEventStorewith a head anchor,verify_chain(), in-place migration of a legacy database, audit adapters and trajectory metrics (stage 1 of #171, ADR 0009). Tamper evidence only: it grants nothing. - Deterministic breaker experiments:
core/breaker_sim.pyandscripts/breaker_reachability.py(breaker reachability). scripts/live_probe.py: drive the classifier + engine offline and record traces.- Emotion-ablation evaluation harness, stage 1:
python -m stiracore.eval(fixed scenarios, scripted runner without LLM calls, opt-in NXPAgent runner). Reports contain measurements only and are not evidence that the emotion module works (pre-registration, #143). - Optional Langfuse/OpenTelemetry exporter.
Two local Flask apps share one shell (base.html, design tokens, sidebar):
- Chat server
dashboard/stira_server.py(/chat,/approvals,/memory,/observability,/settings): turn ribbon + Turn Inspector, in-chat tool cards with masked/paged input and output, approval cards plus an/approvalsqueue with decision history, read-only three-layer memory tree, image attachments. - Observation console
dashboard/app.py(/,/observability,/settings): state and manual stimulus inspection without a live agent. - Settings hub (
/settings): one draft for model/provider, classifier, breaker and tool permissions; presets (safe/standard/developer) with diff preview; change history (JSONL) with field-level rollback; provider settings and connection test. - Japanese by default with an English switch (
?lang=en);scripts/i18n_extract.py --checkvalidates the catalogs. Accessibility gate: axe-core (jsdom) tests and WCAG token contrast checks. Details: dashboard/README.md.
- Slack (Socket Mode), Discord, and signed webhook ingress (chat integrations); OAuth (Authorization Code + PKCE) connector (business integrations).
- Optional tools: Perplexity search (docs/tools/perplexity.md),
bounded web fetch, LSP-style Python analysis (lsp-neural-viz),
page_check— open the agent's own workspace page in a closed browser (no network), click, type and press keys on it, wait for an element or a text, check it with five fixed assertion forms (pass / fail decided by Stira), and get error counts, step results, the page text and screenshots, when Chrome / Chromium / Edge is installed; also onehttp://localhost:<port>server a person allowed on the settings page (no other host or port is reachable); Ask or Never only (ADR 0015);run_checks(opt-in,gateway-config.jsonrun_checks: {"phase": 1}) — run the project's own tests and linters (pytest,unittest,node --test,ruff,compileall) on the agent's code in a throwaway copy with no network; inside a macOS sandbox profile, limits only on Linux; Ask by default (ADR 0019).
scripts/stira_ctl.sh(macOS/Linux) andscripts/stira_ctl.ps1(Windows):start | status | stop | restart | distill, PID-checked stop, refuses an occupied port.- Extras:
dashboard,dev,jev,harness,slack,discord,bedrock, one per provider (anthropic,openai,ollama,gemini,litellm,mistral,writer,llamaapi,sagemaker) andproviders(Anthropic + OpenAI + Ollama). - Executable docs:
tests/test_docs_quickstart.pyruns the quickstart code;tests/test_docs_sync.pykeeps the numbers in AGENTS.md (development repository only) equal to the code, and the environment-variable, config-field and data-directory tables of configuration and the ADR index equal to the code and the files.
ALPHA — experimental. It may change without notice. Do not leave it running unattended on anything you cannot lose. Overview, step-by-step trial and the full list of known limits: docs/autonomy.md.
A person issues a grant for one goal in Settings → Goal grants: a time limit, a token
budget, an iteration limit, a tool scope and one working directory. Issuing it runs nothing.
Each iteration runs in its own session (grant:<id>, not the chat) when the person presses
Run one iteration — or, only if both the server and that grant allow it, when the
scheduler's model-free heartbeat check starts one (at most one per wake). The agent can
report progress, report a blocker or claim the goal is met; only the person confirms
completion. ADR 0011 stage C, #296 (W1–W6d on main).
Switching it on (gateway-config.json, read at start-up; the default in parentheses;
details in configuration):
autonomy.stage_c(false) — the grant control plane: issue, pause, resume, revoke, verify. Runs nothing by itself.autonomy.stage_c_exec(false, needsstage_c) — the iteration executor and the Run one iteration button.autonomy.heartbeat_start(false, needsstage_c_exec) — heartbeat-started iterations. They need all of: this switch, the scheduler (STIRA_SCHEDULER=1), the heartbeat daemon (hb_enabled: trueorSTIRA_HEARTBEAT=1, off by default — without it every wake is skipped), a restart, and a grant issued with its own flag ("Let the heartbeat start iterations", never changed later).autonomy.tick_min_spacing_sec(300, floor 30) — the shortest time from the issue, an iteration's end or a resume to a heartbeat-started iteration.autonomy.run_checks_unattended(true) — whether a grant may includerun_checks; it also needs therun_checkstool on ({"run_checks": {"phase": 1}}, off by default) and a host whose OS sandbox is verified (macOS); otherwise such a grant is refused at issue.autonomy.allow_browser_confirm(false) — permit the weaker browser confirmation when no host channel is configured (STIRA_YOLO_HOST_CONFIRMunset /browser, or YOLO off with everySTIRA_YOLO_*variable butSTIRA_YOLO_ALLOW=offunset — else the server refuses to start); a configured host channel (auto/dialog/command) still takes precedence.autonomy.claim_stale_sec(1800) — when an unverified claim shows "still waiting for you" (display only).autonomy.iteration_wall_sec(600) bounds one iteration.
On the Stage whiteboard (STIRA_STAGE=1, Activity mode): the newest grant, read-only —
its state, iteration n / max, time and budget left, the last end in words, the last five
iterations, "waiting for your approval" / "awaiting your verification" cues, the evidence
measured at a claim and the heartbeat-start counts. No goal text, path or card content; the
controls stay in Settings. The goal text itself is stored only in grants.json (0600),
shown once to the issuer, and sent to the model in each iteration; logs, events and the
other views carry ids and codes only.
Safety model:
- Every grant is issued by a person with a host confirmation (the desktop dialog or
stira approvals decide); without a host channel issue / resume / verify are refused unless the weaker browser layer was chosen explicitly. One live grant per server. - TTL default 2 h, hard cap 6 h, never extended; iterations default 10, cap 20.
- Budgets: a total (≤ 5,000,000 tokens) and a per-iteration limit; each provider request is reserved against them before it is sent and never resets.
- Kill switch and Revoke need no confirmation and refuse every new permit at once (an
effect already running finishes). The kill is then written as a latch that survives
restarts until a person clears it with the server stopped — durable only once the latch
is written (the kill answer says
latch: set;GET /api/authority/statusthen lists"kill"inlatcheswithlatch_store_healthy: true); a restart before the write lands can come up not killed (documented limit)./new, the breaker leaving NORMAL, the TTL, a clock anomaly and every restart stop the grant. - Pre-emption: a person's chat turn (any holder of the turn lock) makes a running iteration yield at its next boundary.
- A permit at every effect: each model call, tool call, approval wait and report is checked against the authority epoch and the grant right before the I/O.
- No approval is answered automatically: an Ask waits for a person's card; a heartbeat-started iteration never waits — it stops and blocks the goal.
- Tools are the grant's scope within
file_read,editor,run_checks, the memory read tools andcurrent_time(no shell, web, delegate or MCP); the editor stays in the working directory;run_checksonly in a verified OS sandbox. - Completion is verified by the person: a claim only waits for verification; the evidence shown is codes the harness measured, never model text.
Known limits include: Amazon Bedrock only; no prompt caching for iterations; per-iteration cost not yet measured on a real model; same-user processes are out of scope; loop detection is not guaranteed for cycles over more than 256 files — see docs/autonomy.md §4.
The web apps are local development servers without authentication. Defaults are fail-closed:
- Exec-class tools are hidden.
shell,batch,cron,use_agent,swarm,graph,thinkare not offered to the model unlessSTIRA_ENABLE_EXEC_TOOLS=1(orget_tools(include_exec=True)); no settings preset enables them. Enabled, every call still asks (Ask rule; they can never be Always). Background execution and a sandbox are not implemented yet (#167). With them enabled, human approvals done by local CLIs (procedural rules, staging) are only as strong as the OS user's permissions: run the agent as a different OS user from the approver, without write access to the data directory'smemory/outsideepisodic/(EC2 guide #318; details in tool-execution-paths). - Breaker-based tool filtering. WARNING withholds write-capable tools. CRITICAL is
read-only by default; with
critical_action="halt"(the chat server) the model still runs, reads continue, and every write-capable tool call needs a human approval (no approver attached → the call is rejected). Only isolated NXP subagents stop before the model call at HALT. - Tool rules and the gate stack (#190): every call is decided by rule → breaker → floor and the strictest layer wins; an Ask approval answers the rule only and never lifts the breaker or the floor. Loosening a rule needs a confirmation and a NORMAL breaker and is audited first; a rules file that fails its integrity check locks every tool to Never until a person saves with the recovery word (ADR 0010, operations).
- HITL approvals are bound to agent, tool, a hash of the arguments, and an expiry; edits become new requests; no answer means reject. An operation ledger prevents duplicate side effects when a checkpoint is replayed (hitl-approvals). Approvals are durable (#240): any doubt at start-up (an interrupted write, rows deleted from the end) cancels every unfinished approval instead of trusting it, a tampered store rejects everything, and a rule saved in between revokes every open approval (ADR 0006). No environment variable approves anything.
- Unattended work stays bounded: the heartbeat never calls a model, and scheduled jobs (opt-in) are created only by a person, use read-only tools, stop at the first call that would need an approval, and do not start above NORMAL (ADR 0008). The opt-in goal grants (alpha) can let the scheduler's model-free check start a goal iteration only inside a grant a person issued for it (autonomy).
- Identity files: SOUL/IPD and configured
read_only_pathsare read-only at every level;protected_dirs(the chat server:memory/procedural) are enforced at the file-tool execution boundary (soul-read-only). - Write roots (#243):
file_write/editormay only write insideAgentConfig.write_roots(default: the agent's workspace). This deny-by-default comes fromAgentConfig; library callers that pass nowrite_policyget the floor only (tool-execution-paths). - Write diagnostics (#244): a failed
file_write/editorbecomes a permission card (what, why, whose permission, steps for a person; one retry);stira doctorchecks the write roots and changes nothing. Command-tool calls that namexattr/chflags/sudo/tccutil/csrutilin plain text are refused (not computed names — exec tools are off by default, #167) (diagnostics). - Tool execution-path contract for standard, MCP and delegated tools (tool-execution-paths, tool-audit).
- Web hardening: Host/Origin checks and CSRF token on every POST, CSP and security
headers, idempotency keys on chat/approval/model endpoints,
mask_secretson tool previews, events, APIs and exports, and a bind guard that refuses non-loopback hosts unlessSTIRA_ALLOW_REMOTE=1. Every route is classified in the admin/API permission matrix. - Credentials are referenced by environment-variable name, never stored or echoed.
Known limits (measured, open): IdentityGuard and the file wrappers are not an OS
sandbox: the write-path check happens at one instant (the editor opens with
O_NOFOLLOW and stira doctor works through directory descriptors, but a concurrent
replacement by another process is out of scope, #167); a tool with no registry entry and
no write-shaped name is treated as read and still runs at CRITICAL; protected_dirs only
applies to file_write / editor (see tool-execution-paths).
The hash chains (approvals, scheduler log, EventStore) have no signature or external
anchor: someone who can write both a database and its head can rebuild a consistent chain
(#277). Since
#271 the data directory is on
the file tools' write floor except workspace/, the episodic layer and the context stash;
the stash can still be written by the agent and is read back unchecked
(#288). Restoring an older
backup brings older, possibly looser tool rules back without a lock
(#273; see
operations §8). autonomy_boundary in
agent-config.json is stored but not enforced
(#272), and one data directory
supports one server process: a second stira_server on the same directory refuses to
start (operations §1,
#285); other programs that open
the directory (e.g. distill while the server runs) are not excluded. The six stimulus categories
lack failure/frustration/pressure (#164),
and very long one-sided dialogs saturate the state (#165).
These are planned or partly designed but do not exist on main:
- Approval-gated exec tools with background execution and sandbox — #167
- ACP client / ACP server / ACP delegation policy — #210, #211, #212
- Associative recall (read-side Amygdala Pass) — #170
- EventStore stages 2–3: chat server wiring of the audit adapters, moving the approval store and the scheduler log onto it, signing or an external anchor — #277 (the remainder of #171)
- Agent-layer (model-calling) scheduled jobs, unattended jobs that wait for an approval, and the rest of the autonomous runtime — #105, #239. Of ADR 0011 (#296), the grant-scoped goal loop exists as an alpha (Autonomy; one supervised real-model smoke ran, W6e); still planned: YOLO two-binding inside an iteration (W7), taint and episodic origin for iterations (W8), a shared day budget pool, and bounded self-scheduling inside a human-defined envelope (stages A and B). Autonomy without a grant, always-on event-driven operation and self-expansion of permissions stay out of scope.
- Prompt cache follow-ups (settings-hub toggle, TTL strategy for heartbeat/cron, MCP tool order) — #254; context-management open points — #258; breaker tool hiding vs runtime refusal (needs a decision) — #259
- Time-limited Always rules and the other open points of ADR 0010 — #190, #270
- Diagnostics tab on the settings page — #267
- Session list / switch / search in the UI — #196
- Formal bcScore definition and COHERENCE behaviour while the window fills — #168
- Multilingual classifier and classifier switching beyond rule/Sokudan — #106
- Emotion-ablation evaluation beyond stage 1 (LLM runs, analysis) — #143
Tracking issues: UI #182, providers/ACP #203.
src/stiracore/
├── core/ # StiraEngine, NeuralState, AmygdalaPass, approvals, checkpoints, breaker_sim
├── agent/ # NXPAgent, ContextAssembler, classifiers, SOUL guard, sessions, subagents
├── providers/ # ModelSpec, create_model, credentials, capabilities, usage, connection test
├── middleware/ # IdentityGuard, Neural State, sycophancy, logging
├── tools/ # 3-layer memory, tool registry, identity-protected file tools, web/LSP tools
├── config/ # validated gateway/agent config and resolution
├── control/ # Harvest distillation, staging review, memory maintenance
├── heartbeat/ # model-free heartbeat gateway and pacing
├── scheduler/ # opt-in operator-defined jobs, chained event log
├── diagnostics/ # write-failure classification, `stira doctor`
├── observability/ # turn events, SSE, settings hub, shell, i18n, security, masking
├── integrations/ # Slack, Discord, webhook, OAuth
└── eval/ # emotion-ablation harness (python -m stiracore.eval)
dashboard/ # Flask apps (stira_server.py, app.py), templates, static assets
docs/ # design, setup, security and research documents
scripts/ # stira_ctl, live_probe, breaker_reachability, i18n_extract, …
tests/ # test suite (offline by default)
- Python 3.11+ (3.11 is the baseline on every OS; the
jevextra needs 3.11) - strands-agents >= 1.57.1
- strands-agents-tools >= 0.8.0, < 0.8.10 (held at the release the exec bridge was audited against)
- A model provider: Amazon Bedrock (default; AWS credentials) or any Strands provider without AWS — Ollama, llama.cpp, OpenAI, Anthropic, Gemini, … — see Model providers
- Flask for the web apps (
dashboardordevextra)
pyproject.toml is the dependency source of truth.
See the OS-specific installation guide for Linux, macOS, and Windows setup, tool compatibility, and starting the observation console or chat UI. 日本語のインストールガイド is also available. For AWS credentials and model access, follow Authentication & Environment.
git clone https://github.com/Resolver-TNG/StiraCore.git
cd StiraCore
python3 -m venv .venv && source .venv/bin/activate # Windows: py -3.11 -m venv .venv
python -m pip install -e '.[dashboard]' # add jev, dev, a provider extra, … as needed
python scripts/smoke_server.py # optional: server starts, /api/config = 200pip install -e '.[ollama]' # or '.[openai]', '.[anthropic]'; llama.cpp needs no extrafrom stiracore import ModelSpec, NXPAgent
agent = NXPAgent(model=ModelSpec("ollama", "llama3.2:3b"))
print(agent("Hello!"))See docs/quickstart.md for the engine without any model, a Bedrock turn, context assembly and persistence, and docs/providers.md for every provider, API-key environment variables, and live smoke tests.
python3 -m venv /tmp/stira-venv && . /tmp/stira-venv/bin/activate
pip install -e ".[dashboard]"Pick one model:
# 1) Fake model (no cloud, no key): the offline stand-in used by the tests
python tests/fake_bedrock_endpoint.py 5690 &
AWS_ENDPOINT_URL_BEDROCK_RUNTIME=http://127.0.0.1:5690 AWS_ACCESS_KEY_ID=dummy \
AWS_SECRET_ACCESS_KEY=dummy AWS_DEFAULT_REGION=us-east-1 STIRA_PORT=5600 \
python dashboard/stira_server.py # every reply is "OK"
# 2) llama.cpp (llama-server on :8080)
STIRA_PROVIDER=llamacpp STIRA_MODEL=local STIRA_BASE_URL=http://127.0.0.1:8080 \
STIRA_PORT=5600 python dashboard/stira_server.py
# 3) Amazon Bedrock (your AWS credentials and model access; see docs/setup.md)
STIRA_PORT=5600 python dashboard/stira_server.pyOpen http://127.0.0.1:5600/chat and send a message. Data goes to <repo>/.local/
(git-ignored). If the model cannot be reached the chat shows a generic error after the turn.
Stage is a pixel-art visual-novel view of what the agent is doing: the character, a text
window with the composer, approvals as a choice window, Neural State and the breaker. It
adds no permission. Start the server with STIRA_STAGE=1 and open /stage/:
STIRA_STAGE=1 STIRA_PORT=5600 python dashboard/stira_server.pyWithout STIRA_STAGE=1 there is no /stage route. A reply's ```svg block is drawn on
the board as a picture rebuilt from an allow-list of shapes, colours and text (no script, link
or outside resource; on by default, off in Settings → "Board (Stage)", ui.board_svg).
Details: docs/stage.md.
- Safety layers — identity guard, SOUL read-only, write/read floors, taint and containment (containment.md, taint.md).
- Approvals — HITL cards bound to the argument hash (hitl-approvals.md).
- Allow again — one press on an approval card allows the same tool on the same folder or host for the conversation (at most 2 hours, in memory, revocable from a badge), or saves the tool as Always through the settings hub once the call has run (allow-again.md).
- YOLO window — a time-boxed, audited auto-approve window. The
Start YOLObutton is shown by default and approves nothing until you press and confirm it;STIRA_YOLO_ALLOW=offhides it (yolo-quickstart.md, ADR 0012 addendum 2026-10-24). - Progress reports — interim reports during long turns (model-progress.md).
- Artifacts — files the agent produces, listed and previewed in the UI.
- page_check / run_checks — browser page checks and allow-listed check commands (tool-definitions.md).
- Scheduler — opt-in scheduled jobs (scheduler.md).
- Goal grants (alpha, off by default) — a person-issued, time-, budget- and scope-limited grant for one goal; iterations by a press or, opt-in, the heartbeat; the person verifies completion (autonomy.md).
- Observability — turns, tools, breaker and cost pages (diagnostics.md).
- Attack regression set —
tests/attack/(attack-regression.md).
macOS (Apple Silicon) — Python 3.11 venv, then:
.venv/bin/python -m pip install -e ".[jev,dashboard]"
scripts/stira_ctl.sh start # status | stop | restart | distillPort 5555 by default; set STIRA_PORT if it is taken (start refuses an occupied port).
Details: install.md §10.
Windows (PowerShell, not verified on Windows) — stira_ctl.ps1 runs
.venv311\Scripts\python.exe, so create that venv (py -3.11 -m venv .venv311), install
into it, then .\scripts\stira_ctl.ps1 start|status|stop. Execution policy and UTF-8 notes:
install.md §4.
Without AWS — point the chat server at a local or hosted provider by environment
variable (or .local/stira/gateway-config.json):
STIRA_PROVIDER=llamacpp STIRA_MODEL=local STIRA_BASE_URL=http://127.0.0.1:8080 \
python dashboard/stira_server.pyFor hosted APIs set STIRA_API_KEY_ENV to the name of the variable holding the key.
Classifiers, memory and rule-based distillation never need AWS
(providers: running without AWS).
| Topic | Document |
|---|---|
| All documents and ADRs | docs/README.md |
| Install (Linux/macOS/Windows) | install.md / install_ja.md |
| Optional: running on an always-on host such as EC2 (a reference setup: private access, instance role, systemd, backup) and the Mac / Windows / EC2 comparison | deploy-ec2.md / deploy-ec2_ja.md |
| Configuration (environment variables, config files, data directory) | configuration.md / configuration_ja.md |
Operations (recovery, stira doctor, backup and restore) |
operations.md / operations_ja.md |
| AWS setup, IAM | setup.md, bedrock-iam-policy.md |
| Quickstart (executed in tests) | quickstart.md |
| Model providers | providers.md / providers_ja.md |
| Architecture and diagrams | architecture.md, diagrams, design-philosophy.md |
| Design decisions | ADR index (ADR 0001–0010) |
| Autonomy (alpha): goal grants, iterations, known limits | autonomy.md / autonomy_ja.md, grants.md, authority-service.md |
| Opt-in features | heartbeat-daemon.md, scheduler.md, prompt-cache.md, context-management.md |
| Memory maintenance (manual runs, OS timer examples, measured token cost; nothing runs by default) | memory-maintenance.md / memory-maintenance_ja.md, examples/memory-maintenance/ |
| Safety | hitl-approvals.md, diagnostics.md, tool-execution-paths.md, tool-audit.md, soul-read-only.md, soul-compaction.md, admin-api-permissions.md |
| Sessions, subagents, checkpoints | harness-components.md, checkpoints.md |
| Integrations | chat-integrations.md, business-integrations.md |
| Web UI | dashboard/README.md |
| Evaluation and measurements | eval prereg, breaker-reachability.md, attack-regression.md |
| For agents running on the harness (development repository only; not in the public release) | AGENTS.md |
- Contributions: CONTRIBUTING.md. Vulnerabilities: report them privately as described in SECURITY.md, not in a public issue.
- Numbers such as
#123in the documentation and code are from the maintainer's private development tracker, not issues of this repository. They are kept as stable IDs for the design history.
- Code: Apache License 2.0 — see LICENSE and NOTICE.
- Stage assets (the pixel-art character, background and props under
dashboard/stage/assets/) and the screenshots indocs/images/: CC BY 4.0 — see LICENSE-ASSETS. Credit Resolver-TNG when you reuse them. - three.js (
dashboard/stage/vendor/): MIT — see NOTICE. - The project's names and logos are not covered by these licences (Apache License 2.0, section 6).
Built by Resolver-TNG — where NXP theory meets production runtime.





