Metadata-Version: 2.4
Name: laserbrain
Version: 0.3.0
Summary: Attach the smart recursion harness to any agent loop — a provably-correct, external check for when an AI agent (or team) has drifted from its goal.
Author: phronesis
License-Expression: MIT
Project-URL: Homepage, https://phronesis.world/laserbrain
Project-URL: Research, https://phronesis.world/laserbrain/research
Project-URL: Demo, https://phronesis.world/laserbrain/demo
Keywords: ai,agents,oversight,drift,mcp,llm,multi-agent
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# laserbrain

Attach the **smart recursion harness** to any agent loop — a provably-correct,
external check for when an AI agent (or a team of agents) has drifted from its goal.

An agent watching only itself provably can't catch its own drift: each step looks
fine next to the last while it wanders far from where it began. laserbrain is a
**fixed reference** it checks against instead. There's a proof.
[The theorem and the studies (nulls included).](https://phronesis.world/laserbrain/research)
· [Watch it work.](https://phronesis.world/laserbrain/demo)

The check is a pure function, so this SDK runs it **locally and free** — no key, no
latency. Add a key and it also mirrors to the API for retained drift history,
alerts and the fleet view: you pay to *see* your agents drift, not for the check.

```bash
pip install laserbrain
```

See it work before writing any code:

```bash
laserbrain demo          # watch an agent drift off-goal and get returned
laserbrain check --goal "write a poem" --against "build a parser"   # a one-shot drift check
```

## The check (local, free)

```python
from laserbrain import Harness

hz = Harness()                      # add key="lb_live_…" to also retain history
v = hz.check(goal="build the JSON parser", progress="advancing", distance=6)
if v.drifting:
    print(v.reason, "—", v.advice)  # e.g. "goal-drift — your goal no longer matches…"
```

`progress` is one of `advancing | stuck | circling`; `distance` is 0–10 to done.
Reasons: `advancing`, `grounded`, `goal-drift`, `stalled`, `self-report:stuck/circling`,
`ungrammatical`. Want a bounded reading instead of a raw distance? `v.ground_score`
maps Φ to `[0,1]` — `1.0` fully grounded, falling as it drifts (`1/(1+4·Φ)`).

## The act layer — close the loop

Give laserbrain your step function and it detects drift *and* injects the return, so
the agent recovers instead of spinning. Your step reads `ctx["return"]` and steers back.

```python
def step(ctx):
    if ctx.get("return"):            # laserbrain told us to return to ground
        ...                          # steer the agent back toward its goal
    ...
    return dict(goal="build the JSON parser", progress="advancing", distance=d, done=d == 0)

ctx = Harness().run(step, on_return=lambda v, ctx: print("↩", v.advice))
```

## Recursion teams — styled multi-agent oversight

A **recursion team** styles each role's recursion: a `deep` explorer tolerates
displacement, a `tight` checker returns fast. laserbrain runs the team, watches the
shared goal (the fixed reference), and injects the return per role — catching the
**echo/agreement spiral** a self-watching group can't see.

```python
from laserbrain import Team

def agent(role, history, injected):
    # your LLM call for this role; `injected` is a return-to-ground note (or None)
    return position, distance

Team("adversarial-deliberation", goal="…").run(agent)
# presets: deep-search · iterative-refinement · adversarial-deliberation
```

## Oversight, provenance, continuity

**Human-in-the-loop.** A self-correcting return usually takes. When it doesn't —
the agent keeps drifting past `escalate_after` steps — laserbrain escalates *that
drift* to a human. The human doesn't watch every step; they see only what the fixed
reference caught. Their decision overrides the auto-return.

```python
def on_escalate(v, ctx):
    return ask_a_human(v.reason, v.advice)     # Slack, a queue, a webhook — you wire it
                                               # returning a decision injects it as the return
Harness().run(step, escalate_after=3, on_escalate=on_escalate)
```

**Provenance.** Every check is written to a hash-chained ledger — tamper-evident and
verifiable offline, by anyone, no key. Editing a past verdict to hide a drift breaks
the chain at that link.

```python
hz.export_audit("run.json")
from laserbrain import verify_audit
verify_audit(json.load(open("run.json")))      # (True, -1) intact · (False, i) broken at link i
```

**Team continuity.** Snapshot a running team and resume it in a later session — the
shared goal (the fixed reference) and the dialogue carry over, so the group re-grounds
instead of starting cold.

```python
snap = team.snapshot()                         # JSON-safe; persist it anywhere
team = Team.restore(snap)                       # keeps watching the same ground
```

## Framework adapters

Already on LangGraph, CrewAI, AutoGen, or the OpenAI Agents SDK? Attach laserbrain
without changing your loop. Because it checks a fixed reference, it needs the agent
to *spell* its state — so each adapter takes an `extract` that maps your framework's
state to `(goal, progress, distance)`. **No adapter imports a framework**: each
returns a plain callable you hand to the framework's own hook, so install only the
one you use.

```python
from laserbrain.adapters import guard, langgraph_node, crewai_step_callback, middleware

# generic — wrap any step that returns dict(goal=, progress=, distance=)
@guard
def step(state): ...

# LangGraph — a node that writes the Verdict into graph state; branch on it
g.add_node("laserbrain", langgraph_node(extract=lambda s: (s["goal"], "advancing", s["dist"])))
g.add_edge("agent", "laserbrain")
g.add_conditional_edges("laserbrain",
    lambda s: "return" if s["laserbrain"].drifting else "agent")   # .advice steers the return

# CrewAI — a step_callback that fires each agent step
Agent(..., step_callback=crewai_step_callback(lambda o: (o.goal, o.status, o.dist)))

# anything else (AutoGen, OpenAI Agents, a custom loop) — one check per step
lb = middleware(extract=my_extract)
v = lb(step_output)
if v.drifting: reinject(v.advice)
```

Each adapter runs the check locally and free; pass `key=`/`run_id=` (or your own
`Harness`) to also retain history.

## What's proven, and what isn't

The **single-agent** detector mirrors the frozen, published instrument
(`drift.ts @ 6b483de7`) and rests on a theorem: detection is sound and complete, and
no self-monitoring agent can be. The **multi-agent** dialogue and recursion teams are
a prototype extension — useful, not (yet) a theorem. Whether *returning* an agent
keeps the answer as good is [an honest open question](https://phronesis.world/laserbrain/research);
this SDK gives you the detection and the return mechanism, and says plainly what each is.

MIT · [phronesis.world/laserbrain](https://phronesis.world/laserbrain)
