API reference¶
The typed public API, rendered from docstrings. Reigner has no untyped public surfaces, so signatures here are authoritative.
Top-level package¶
Reigner: a single-agent, retrieval-shaped, citation-faithful agent library.
Plugin ¶
Base for all plugins. Override the hooks you need; the rest no-op.
name is used in logs and error messages; it defaults to the class name
when left blank.
before_tool_call
async
¶
Inspect or rewrite a tool call before it runs. Return the call.
after_tool_call
async
¶
Inspect or rewrite a tool result after truncation. Return the result.
result is the bounded :class:ToolResultEvent (so result.truncated
is meaningful); a returned copy with a rewritten result payload is
what lands in both the model's context and the emitted event.
on_compaction
async
¶
Observe a compaction tier firing (level is the tier index).
on_final_answer
async
¶
Inspect or rewrite the final answer before it is emitted.
on_error
async
¶
Observe a terminal error before it is emitted.
on_oracle_escalation
async
¶
Observe a single-turn oracle escalation being armed.
on_steering
async
¶
Observe a queued steering message being accepted into the loop.
SessionStore ¶
Filesystem-backed store of session JSONL + meta sidecars.
One :class:SessionStore is owned by a :class:Harness; every
:class:Session shares it. The store doesn't cache file handles — each
:meth:append_event opens, writes, flushes, closes. Crash-safe per event
at the cost of one open per event; that's the trade we want for an
artifact you debug after the fact.
list ¶
Return meta for every session under the root, sorted by id.
Malformed sessions (unreadable JSONL, version mismatch) are skipped so a single broken file doesn't poison the listing.
append_event ¶
Serialize event and append it as one line to {sid}.jsonl.
Flushes after each write so a crash mid-conversation loses at most
the in-flight event. Meta is not touched here — call :meth:write_meta
when summary fields need refreshing.
write_session_events ¶
Write event_list as the complete JSONL for session_id (overwrites).
Used by :meth:Session.fork to snapshot a parent's event prefix into a
fresh child file. The caller owns session_id consistency — events
whose session_id field doesn't match are written as-is, so rewrite
them (dataclasses.replace) before calling if a self-contained
transcript is wanted. Returns the number of events written.
load_events ¶
Iterate the events of one session in write order.
Streaming on purpose: long sessions stay friendly to memory. Callers
that want a list should wrap with list(...).
read_meta ¶
Return meta for session_id, rebuilding from JSONL if missing.
If the sidecar exists it's the source of truth; if absent we scan the
events to fill in what we can (event_count, created,
last_updated). parent_id and title are unrecoverable from
events alone and default to None after a rebuild.
write_meta ¶
Atomically write meta to the sidecar via tmp + os.replace.
set_title ¶
Set (or clear) a session's title and return the updated metadata.
export ¶
Write the session's JSONL to dest_path plus a sidecar meta.
Takes a single .jsonl path and emits {dest}.meta.json next to
it so title/created/parent_id survive the round trip.
Returns:
| Type | Description |
|---|---|
Path
|
The destination JSONL path. |
import_ ¶
Import a previously-exported session into this store.
Reuses the source session_id (from the sidecar meta if present,
otherwise from the first event in the JSONL). On collision with an
existing local session id, raises :class:FileExistsError so the
caller can rename or delete the existing one. Returns the session id.
SessionMeta
dataclass
¶
Summary record for one session, persisted as {sid}.meta.json.
total_tokens and total_cost are deliberately absent — no event
carries them yet. They'll be added as fields when later tasks emit usage
events; the schema_version bumps in lockstep so old sessions still
load via a migration path.
from_json
classmethod
¶
Parse :class:SessionMeta from its JSON form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw
|
str
|
JSON text previously produced by :meth: |
required |
Returns:
| Type | Description |
|---|---|
SessionMeta
|
The decoded metadata. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the JSON root is not an object. |
SchemaVersionMismatch
|
If the stored version is unsupported. |
tool ¶
tool(
*,
readonly: bool = False,
cache: bool = False,
truncate_chars: int | None = None,
description: str | None = None,
pseudo: bool = False,
) -> Callable[[F], F]
Decorate an async function as a Reigner tool.
Validates MCP-clean constraints at decoration time, generates a JSON Schema
for the arguments via Pydantic, and attaches a ToolSpec to the function
as __reigner_spec__. The original callable is returned unchanged — direct
calls work in tests without going through the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
readonly
|
bool
|
Eligible for G9 caching and G11 parallel execution. |
False
|
cache
|
bool
|
Opt-in result caching keyed on (name, args). |
False
|
truncate_chars
|
int | None
|
Per-tool override of the G2 truncation budget. |
None
|
description
|
str | None
|
Overrides the function's docstring on the tool schema. |
None
|
pseudo
|
bool
|
Intercepted locally by the loop; implies |
False
|
Returns:
| Type | Description |
|---|---|
Callable[[F], F]
|
A decorator that attaches a |
Tools¶
reigner.tools ¶
Reigner tool system — the @tool decorator, registry, and built-in tools.
ToolResult
module-attribute
¶
Documented type alias for tool return values.
Calls for bounded, self-describing results (has_more, truncated,
available_keys). Not enforced as a class because the right self-description
fields vary by tool.
ArtifactStore ¶
Schema-aware view of a compiled artifact root for read-side tools.
resolve ¶
Resolve a root-relative path, rejecting traversal escapes.
rel must be a non-empty relative POSIX-style path. The resolved
path is rejected if it doesn't stay under self.root.
resolve_entity ¶
Resolve an entity directory from its entity_path identifiers.
tools ¶
Build the six built-in artifact tools as RunnableTool wrappers.
ToolDefinitionError ¶
Bases: TypeError
Raised at decoration time when a function violates MCP-clean constraints.
ToolSpec
dataclass
¶
Metadata + invocation handle for a registered tool.
Structurally satisfies harness.state.ToolSpec Protocol — name,
description, readonly, and json_schema() are the surface AgentState
reads. The remaining flags (cache, truncate_chars, pseudo) are
consumed by the loop guardrails and by profile filtering in the registry.
FsTools ¶
Root-bound sandbox for raw filesystem tools.
Pass exactly one of root (single-root mode) or roots (multi-root
mode). See the module docstring for how the two modes differ.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str | Path | None
|
Single directory the agent is allowed to see. All tool paths are
interpreted relative to this root and validated against it. Mutually
exclusive with |
None
|
roots
|
dict[str, str | Path] | None
|
Name→directory map exposed as one virtual tree. Each root name
becomes a top-level directory; the first path segment selects the
root. Mutually exclusive with |
None
|
write_enabled
|
bool
|
When True, |
False
|
max_read_chars
|
int
|
Per-call character cap for |
8000
|
max_grep_matches
|
int
|
Total match cap for |
20
|
max_ls_entries
|
int
|
Entry cap for |
200
|
max_glob_results
|
int
|
Result cap for |
200
|
text_extensions
|
frozenset[str] | set[str] | None
|
Suffix allowlist (lowercase, with leading dot)
for |
None
|
ignored_dirs
|
frozenset[str] | set[str] | None
|
Directory basenames skipped during recursive walks. |
None
|
iter_roots ¶
(name, absolute-path) for every root, in configured order.
resolve ¶
Resolve a virtual-tree path, rejecting traversal escapes.
rel must be a non-empty relative POSIX-style path. In single-root
mode it is interpreted directly under the sole root. In multi-root mode
the first segment names the root and the remainder is validated inside
that root. Returns (root_name, absolute_path) — root_name is
"" in single-root mode.
The resolved path is rejected if it doesn't stay under its selected
root: this catches both .. traversal and symlinks pointing outside
the root (Path.resolve() follows symlinks before the check).
display ¶
Render an absolute path as the agent-facing virtual-tree string.
Root-relative in single-root mode; root-prefixed (name/rel) in
multi-root mode so cross-repo references stay unambiguous.
is_ignored ¶
True if path should be skipped during walks.
Skips any segment in :attr:ignored_dirs. When include_hidden
is False (the default), also skips any segment starting with .
except the ./.. placeholders. Segments are measured relative
to base — the owning root a caller already knows; when omitted it
is inferred (a path outside every root is treated as ignored).
is_text_extension ¶
True if path's suffix is in :attr:text_extensions.
tools ¶
Build the FS tools as RunnableTool wrappers.
Returns four tools by default (fs_read, fs_grep,
fs_glob, fs_ls); fs_write is appended only when
:attr:write_enabled is True.
ToolRegistrationError ¶
Bases: ValueError
Raised when a tool can't be registered (missing spec, name collision).
ToolRegistry ¶
In-memory map of tool name → ToolSpec, scoped to one Harness.
Construct empty, then register decorated functions or bare ToolSpecs.
The Session asks for for_profile(profile) to get its tool surface for
each call; nothing here mutates per-session state.
register ¶
Register a decorated function, a bare ToolSpec, or a RunnableToolAdapter.
Returns the underlying spec.
Raises ToolRegistrationError on
- a function without
__reigner_spec__(forgot @tool) - a name already present in the registry
schemas ¶
JSON Schema list for every registered tool, in insertion order.
Provider-agnostic. Model adapters translate to provider-specific tool-schema shapes.
for_profile ¶
Return the tool subset visible under profile as adapters.
full — every registered tool.
read_only — readonly tools plus pseudo-tools.
eval — readonly tools plus pseudo-tools except escalate_to_oracle
and request_clarification (both defeat determinism).
Adapters are constructed fresh on each call; with ~10 tools per harness
the allocation cost is negligible. The loop wants .run(args), so this
is the call site that hands out runnables.
tool ¶
tool(
*,
readonly: bool = False,
cache: bool = False,
truncate_chars: int | None = None,
description: str | None = None,
pseudo: bool = False,
) -> Callable[[F], F]
Decorate an async function as a Reigner tool.
Validates MCP-clean constraints at decoration time, generates a JSON Schema
for the arguments via Pydantic, and attaches a ToolSpec to the function
as __reigner_spec__. The original callable is returned unchanged — direct
calls work in tests without going through the registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
readonly
|
bool
|
Eligible for G9 caching and G11 parallel execution. |
False
|
cache
|
bool
|
Opt-in result caching keyed on (name, args). |
False
|
truncate_chars
|
int | None
|
Per-tool override of the G2 truncation budget. |
None
|
description
|
str | None
|
Overrides the function's docstring on the tool schema. |
None
|
pseudo
|
bool
|
Intercepted locally by the loop; implies |
False
|
Returns:
| Type | Description |
|---|---|
Callable[[F], F]
|
A decorator that attaches a |
Sessions¶
reigner.sessions ¶
Forkable, branchable, durable sessions.
ReplayError ¶
Bases: ValueError
Raised when an event log can't be reconstructed.
The common case: a session recorded under SCHEMA_VERSION 1 (before
UserQueryEvent) has no query rows, so there's nothing to seed a round
from. Such sessions remain inspectable via Session.events() but cannot
be reconstructed, forked, or replayed.
InvalidSessionId ¶
Bases: ValueError
Raised when a session id contains characters that aren't filename-safe.
SessionMeta
dataclass
¶
Summary record for one session, persisted as {sid}.meta.json.
total_tokens and total_cost are deliberately absent — no event
carries them yet. They'll be added as fields when later tasks emit usage
events; the schema_version bumps in lockstep so old sessions still
load via a migration path.
from_json
classmethod
¶
Parse :class:SessionMeta from its JSON form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw
|
str
|
JSON text previously produced by :meth: |
required |
Returns:
| Type | Description |
|---|---|
SessionMeta
|
The decoded metadata. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the JSON root is not an object. |
SchemaVersionMismatch
|
If the stored version is unsupported. |
SessionNotFound ¶
Bases: FileNotFoundError
Raised when a session id has no JSONL file under the store root.
SessionStore ¶
Filesystem-backed store of session JSONL + meta sidecars.
One :class:SessionStore is owned by a :class:Harness; every
:class:Session shares it. The store doesn't cache file handles — each
:meth:append_event opens, writes, flushes, closes. Crash-safe per event
at the cost of one open per event; that's the trade we want for an
artifact you debug after the fact.
list ¶
Return meta for every session under the root, sorted by id.
Malformed sessions (unreadable JSONL, version mismatch) are skipped so a single broken file doesn't poison the listing.
append_event ¶
Serialize event and append it as one line to {sid}.jsonl.
Flushes after each write so a crash mid-conversation loses at most
the in-flight event. Meta is not touched here — call :meth:write_meta
when summary fields need refreshing.
write_session_events ¶
Write event_list as the complete JSONL for session_id (overwrites).
Used by :meth:Session.fork to snapshot a parent's event prefix into a
fresh child file. The caller owns session_id consistency — events
whose session_id field doesn't match are written as-is, so rewrite
them (dataclasses.replace) before calling if a self-contained
transcript is wanted. Returns the number of events written.
load_events ¶
Iterate the events of one session in write order.
Streaming on purpose: long sessions stay friendly to memory. Callers
that want a list should wrap with list(...).
read_meta ¶
Return meta for session_id, rebuilding from JSONL if missing.
If the sidecar exists it's the source of truth; if absent we scan the
events to fill in what we can (event_count, created,
last_updated). parent_id and title are unrecoverable from
events alone and default to None after a rebuild.
write_meta ¶
Atomically write meta to the sidecar via tmp + os.replace.
set_title ¶
Set (or clear) a session's title and return the updated metadata.
export ¶
Write the session's JSONL to dest_path plus a sidecar meta.
Takes a single .jsonl path and emits {dest}.meta.json next to
it so title/created/parent_id survive the round trip.
Returns:
| Type | Description |
|---|---|
Path
|
The destination JSONL path. |
import_ ¶
Import a previously-exported session into this store.
Reuses the source session_id (from the sidecar meta if present,
otherwise from the first event in the JSONL). On collision with an
existing local session id, raises :class:FileExistsError so the
caller can rename or delete the existing one. Returns the session id.
SessionNode
dataclass
¶
One session in a fork tree.
reconstruct ¶
reconstruct(
events: Sequence[Event],
*,
settings: SettingsConfig,
session_id: str,
role: str = "",
) -> AgentState
Synchronous wrapper around :func:areconstruct.
Session.load / Session.fork are sync, but the loop is
async. We run the coroutine to completion on a private event loop: directly
via asyncio.run when no loop is running, otherwise on a worker thread so
the call is safe from inside async code (e.g. async tests). The
reconstruction is fully self-contained (stub adapter/tools, no shared I/O),
so a separate loop is harmless.
round_boundaries ¶
Indices of every UserQueryEvent — one per conversational round.
at_turn=N (1-based) refers to round_boundaries(events)[N - 1].
build_forest ¶
Build all session families from persisted parent_id relationships.
Sessions with a missing parent are roots. Corrupt cyclic lineage never creates a recursive graph: the edge that would close a cycle is skipped, promoting that node to a root instead.
Plugins¶
reigner.plugins ¶
Hook-based extension points for the agent loop.
Subclass :class:Plugin, override the hooks you need, and list the dotted path
in reigner.yaml under plugins:. :class:PluginHost is the dispatcher
the loop drives; most users never touch it directly.
Two plugins ship in the box: :class:MetricsPlugin (OpenTelemetry spans, needs
the otel extra) and :class:PiiRedactPlugin (regex redaction of tool results
and the final answer). Importing them here is cheap — neither pulls a heavy
dependency at import time; MetricsPlugin only touches OpenTelemetry when
instantiated.
Plugin ¶
Base for all plugins. Override the hooks you need; the rest no-op.
name is used in logs and error messages; it defaults to the class name
when left blank.
before_tool_call
async
¶
Inspect or rewrite a tool call before it runs. Return the call.
after_tool_call
async
¶
Inspect or rewrite a tool result after truncation. Return the result.
result is the bounded :class:ToolResultEvent (so result.truncated
is meaningful); a returned copy with a rewritten result payload is
what lands in both the model's context and the emitted event.
on_compaction
async
¶
Observe a compaction tier firing (level is the tier index).
on_final_answer
async
¶
Inspect or rewrite the final answer before it is emitted.
on_error
async
¶
Observe a terminal error before it is emitted.
on_oracle_escalation
async
¶
Observe a single-turn oracle escalation being armed.
on_steering
async
¶
Observe a queued steering message being accepted into the loop.
PluginHost ¶
Dispatches the seven hooks across an ordered list of plugins.
empty
classmethod
¶
A host with no plugins — every hook is a pass-through no-op.
before_tool_call
async
¶
Fold before_tool_call across plugins; raise on the first failure.
after_tool_call
async
¶
Fold after_tool_call across plugins; raise on the first failure.
on_final_answer
async
¶
Fold on_final_answer across plugins; raise on the first failure.
on_compaction
async
¶
Notify every plugin of a compaction pass; failures are isolated.
on_error
async
¶
Notify every plugin of an error event; failures are isolated.
on_oracle_escalation
async
¶
Notify every plugin of an oracle escalation; failures are isolated.
on_steering
async
¶
Notify every plugin of a steering message; failures are isolated.
MetricsPlugin ¶
Bases: Plugin
Trace tool calls and loop events as OpenTelemetry spans.
before_tool_call
async
¶
Open a span for the tool call, closed by :meth:after_tool_call.
after_tool_call
async
¶
Close the tool-call span, annotating it with truncation/cache flags.
on_compaction
async
¶
Emit a span for a compaction pass.
on_error
async
¶
Emit a span for an error event.
on_oracle_escalation
async
¶
Emit a span for an oracle escalation.
on_steering
async
¶
Emit a span for a steering message.
PiiRedactPlugin ¶
Bases: Plugin
Replace regex matches with a token in tool results and the final answer.
__init__ ¶
Compile patterns up front so a bad pattern fails loudly at wiring time.
Each entry is a regex string or an already-compiled pattern. token is
the replacement substituted for every match.
after_tool_call
async
¶
Scrub the result payload before it lands in the model's context.
on_final_answer
async
¶
Scrub the answer text before it is emitted to the user.
load_plugins ¶
Resolve dotted paths to live :class:Plugin instances, in order.
Artifacts¶
reigner.artifacts ¶
Artifact system — schema, writer, manifest, and conventions.
This package owns the write side and the schema contract; the read-side
ArtifactStore lives in reigner.tools.artifacts.
ExtractionMeta
dataclass
¶
Per-entity manifest written alongside an entity's artifacts.
Attributes:
| Name | Type | Description |
|---|---|---|
schema_version |
str
|
Version of the artifact schema used for extraction. |
identifiers |
dict[str, str]
|
Identity fields locating the entity (e.g. |
files |
list[str]
|
Artifact file paths written for this entity, relative to root. |
extractor |
dict[str, Any] | None
|
Optional extractor-owned payload (hashes, model, cost). |
written_at |
str
|
ISO-8601 UTC timestamp of when the manifest was written. |
from_json
classmethod
¶
Reconstruct an :class:ExtractionMeta from its JSON form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
str
|
JSON text previously produced by :meth: |
required |
Returns:
| Type | Description |
|---|---|
ExtractionMeta
|
The decoded manifest, defaulting |
ArtifactSchema
dataclass
¶
Declarative shape of compiled artifacts on disk.
Used by the writer to lay out files and validate extraction outputs and by the read-side ArtifactStore to know what paths and field names are valid.
entity_path_keys ¶
Return the placeholder names in entity_path, in order.
required_sections ¶
Return the non-glob sections that must be present.
section ¶
Look up a section by exact name, falling back to glob prefixes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Section name to resolve. |
required |
Returns:
| Type | Description |
|---|---|
SectionSpec | None
|
The matching :class: |
json_artifact ¶
Look up a JSON artifact spec by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Artifact filename to resolve. |
required |
Returns:
| Type | Description |
|---|---|
JsonArtifactSpec | None
|
The matching :class: |
document_qa_default
classmethod
¶
Default schema for the document_qa recipe.
generic_default
classmethod
¶
Default schema for non-uniform / mixed corpora.
Where :meth:document_qa_default assumes every document shares a shape,
this offers corpus-agnostic sections any document can fill: one required
summary slot, the rest optional. Use it when a single corpus mixes
document kinds (a textbook, a law, a manual) that no fixed schema fits.
Section targeting is weaker as a result — a document may leave most slots empty — so retrieval recovers the long tail via bm25 over the raw text rather than relying on well-populated sections.
from_yaml
classmethod
¶
Load and validate a schema from a YAML file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to the schema YAML file. |
required |
Returns:
| Type | Description |
|---|---|
ArtifactSchema
|
The parsed :class: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the YAML root is not a mapping. |
to_json_schema ¶
Return a JSON Schema describing the expected extraction output.
The schema describes an object with two top-level keys: sections
(mapping section name → str) and json_artifacts (mapping filename →
object). The LLMExtractor consumes this for its prompt template; the
design here is intentionally minimal.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A JSON-Schema mapping for the extractor's structured output. |
JsonArtifactSpec
dataclass
¶
A JSON artifact under the entity directory.
fields declares expected top-level keys and their Python types. By
default every declared field is required; pass required_fields to
relax this. An empty fields dict means "no field-level validation"
and the artifact is treated as optional.
required_field_names
property
¶
Field names that must be present (all declared fields by default).
SectionSpec
dataclass
¶
A prose-section artifact under the entity directory.
Section names containing * are globs: they declare an allowed prefix
(e.g. sections/*) but cannot be required, since there is no fixed
name to enforce.
is_glob
property
¶
Whether the section name is a glob prefix rather than a fixed name.
ArtifactWriteError ¶
Bases: RuntimeError
Raised on filesystem-level write failures.
ArtifactWriter ¶
Schema-aware, atomic writer for an entity's compiled artifacts.
Bound to an artifact root and a schema; the only sanctioned way to write
under library/artifacts/. Write-side only — never exposed as a tool.
write_entity ¶
write_entity(
*,
sections: dict[str, str] | None = None,
json_artifacts: dict[str, dict[str, Any]] | None = None,
meta: dict[str, Any] | None = None,
**identifiers: str,
) -> Path
Atomically write all artifacts for one entity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sections
|
dict[str, str] | None
|
section name -> prose content. Section names match
|
None
|
json_artifacts
|
dict[str, dict[str, Any]] | None
|
JSON artifact filename -> payload dict. |
None
|
meta
|
dict[str, Any] | None
|
extractor-owned manifest fields ( |
None
|
**identifiers
|
str
|
the entity_path placeholders (e.g. |
{}
|
Returns:
| Type | Description |
|---|---|
Path
|
The absolute entity directory. |
entity_dir ¶
Resolve the absolute entity directory under the writer's root.
SchemaValidationError ¶
Bases: ValueError
Raised when sections or JSON artifacts violate the schema.