keelgate.loop¶
Stability of each symbol (stable or provisional) is listed in the API contract. Narrative and semantics are in the integration contract.
Durable, budgeted agent loop with explicit stop conditions and resume.
AcceptAllVerifier
¶
Accepts everything. For tests and loops where nothing needs checking.
ActionOutcome
¶
Bases: BaseModel
What happened to one planned action: status, error code and fixed-wording detail, and the tool output as untrusted JSON text.
ActionStatus
¶
Bases: StrEnum
Where a planned action stands: pending, done, denied, error, awaiting approval, unknown (may or may not have happened) or abandoned.
CallableVerifier
¶
Wraps a plain function (sync or async) returning a Verdict, a decision or a bool.
CheckpointStore
¶
Bases: Protocol
Where loop state is saved after every step.
save is atomic and refuses a sequence number that is not newer, so a stale writer cannot
overwrite a newer checkpoint; load returns the latest state.
ContextSource
¶
Bases: Protocol
Supplies extra context for a plan step, such as retrieved memory.
Items must be dated (published_at) and untrusted; the builder enforces both.
Divergence
dataclass
¶
One difference between a recorded run and its replay: where, what was expected and what was seen.
GroundedAnswerVerifier
¶
A deterministic verifier: is the final answer supported by what the tools returned?
Two rules, both cheap and both explainable:
- Grounded figures. Every number in the answer (other than a small whole number such as "3") must appear in the goal or in a tool observation. A fabricated or transposed price has nowhere to come from.
- Honest claims. If
write_toolsis given and the answer says something was bought, sold, placed or executed (and does not say it did not), at least one of those tools must have actually completed.
It cannot judge meaning, so it is a floor under a model-based verifier, not a replacement. It never authorises anything: only the gateway does that.
HistoryCheckpointStore
¶
Bases: CheckpointStore, Protocol
A store that keeps every checkpoint, oldest first. Replay needs this.
InMemoryCheckpointStore
¶
Process-local. Fine for tests; it does not survive the process, so it cannot resume.
InProcessRunner
¶
Runs the loop in the calling process.
LLMPlanner
¶
Plans by function calling: tool calls are actions, plain text is a final answer.
LLMVerifier
¶
Asks a model for a JSON verdict. Anything it cannot parse is a rejection.
Loop
¶
The durable agent loop: plan, act, observe, verify, then revise or stop.
Checkpoints every step, honours the stop conditions, and resumes without re-planning or repeating a completed WRITE.
reconcile
async
¶
reconcile(
tenant_id: str,
run_id: str,
action_id: str,
*,
executed: bool,
by: str,
note: str = "",
) -> LoopState
A human settles an action whose outcome was unknown.
executed=True records it as done; executed=False abandons it. Either way the
action is never run again. If it must be attempted afresh, plan a new action with a
new idempotency key.
resume
async
¶
Continue a stopped or interrupted run from its latest checkpoint.
Pass a new stop to continue after a budget stop with a larger budget.
run
async
¶
run(
*,
goal: str,
tenant_id: str,
agent_id: str,
as_of: datetime,
run_id: str | None = None,
trace_id: str | None = None,
stop: StopConditions | None = None,
) -> LoopResult
Start a new run. Refuses an id that already has a checkpoint.
run_or_resume
async
¶
run_or_resume(
*,
goal: str,
tenant_id: str,
agent_id: str,
as_of: datetime,
run_id: str,
trace_id: str | None = None,
stop: StopConditions | None = None,
) -> LoopResult
Idempotent start: resume the run if it exists, otherwise begin it.
LoopOutcome
dataclass
¶
The serialisable result of a run.
LoopResult
dataclass
¶
What a Loop run or resume returns.
The final state, why it stopped, whether it reached the goal and whether it can be resumed.
LoopRunner
¶
Bases: Protocol
Starts a run, or resumes it if a checkpoint exists. Safe to call again after a crash.
LoopSpec
dataclass
¶
Everything needed to start or resume one run, as plain data.
LoopState
¶
Bases: BaseModel
Everything a run needs to resume: the goal, the phase, the planned actions and their outcomes, usage, and the trace identity.
This is what is checkpointed.
LoopType
¶
Bases: StrEnum
The kind of run: a TASK, a read-only VERIFICATION, or a MONITOR tick.
MonitorLoop
¶
Runs a bounded loop on a schedule, finishing a half-done tick after a restart.
Each tick is its own run, named <monitor_id>.tick-<n>, so ticks are checkpointed and
resumable independently. The next tick number comes from what is already stored: a
restarted monitor carries on rather than starting over.
loop_factory is called as loop_factory(loop_type=..., allowed_side_effects=...)
and must pass both through to the :class:Loop it builds.
MonitorSummary
dataclass
¶
The outcome of a bounded monitoring session: how many ticks ran and each tick's result.
NotReplayableError
¶
Bases: Exception
The recording lacks a recorded result for some action, or the run cannot be found.
OutcomeConfirmer
¶
Bases: Protocol
Settles an action whose outcome is unknown by asking the downstream system of record.
Return True if the action took effect, False if it definitely did not, and None
when the answer is not certain (the loop then stops for a human, as before).
Phase
¶
Bases: StrEnum
Where a run is in its cycle: plan, act, observe, verify, or done.
Plan
dataclass
¶
What the planner proposed: actions to run, or a final answer, never both.
PlanRequest
dataclass
¶
What the planner is given for one planning call.
The run, the iteration, the built context messages and the tools it may propose.
PlannedAction
¶
Bases: BaseModel
One tool call the planner chose, written down before it runs so a resume re-submits the same arguments.
Planner
¶
Bases: Protocol
Proposes the next step: tool calls to run, or a final answer.
A planner is untrusted; its proposals go through the gateway like any other.
ProposedAction
dataclass
¶
One tool call the planner proposes: a tool name, untrusted arguments and a rationale.
A proposal only; the gateway decides.
RecordedAction
dataclass
¶
One tool call as recorded in a run: name, arguments, final status and outcome.
RecordedStep
dataclass
¶
One iteration of a recorded run: the actions proposed, the final answer if any and the verdict.
Recording
dataclass
¶
A run rebuilt from its checkpoint history, ready to replay.
Find one by trace id with Recording.from_store.
from_store
classmethod
¶
from_store(
store: CheckpointStore,
tenant_id: str,
*,
trace_id: str | None = None,
run_id: str | None = None,
) -> Recording
Rebuild a run by trace id (or run id) from a store that keeps history.
ReplayReport
dataclass
¶
The result of a replay: the original and replayed recordings and every divergence.
identical is true when there is none.
RunExistsError
¶
Bases: Exception
run was asked to start a run id that already has a checkpoint.
RunNotFoundError
¶
Bases: Exception
resume found no checkpoint for that tenant and run id.
Schedule
dataclass
¶
A fixed interval between monitoring ticks.
SqliteCheckpointStore
¶
Durable, dependency-free. Keeps every checkpoint, so a run's history can be inspected.
StaleCheckpointError
¶
Bases: Exception
A newer checkpoint already exists: another writer got there first.
StopConditions
dataclass
¶
Limits for one run.
max_iterations counts plan steps. max_tokens and max_dollars count what the
model has already used, so a call that crosses the line is accepted, but nothing
further is paid for or acted on. timeout is active time: time spent stopped,
for example waiting for a human, does not count. max_verifier_rejections counts every
non-ACCEPT verdict. goal is checked after each observation.
A dollar budget needs a priced model; with an unpriced one the loop stops with
COST_UNKNOWN instead of spending unmetered.
StopReason
¶
Bases: StrEnum
Why a run stopped: the goal was reached, a limit was hit (iterations, tokens, dollars, time), the verifier rejected too often, an outcome is unknown, an approval is pending, or an error.
Verdict
dataclass
¶
A verifier's judgement of a proposed final answer.
Accept, revise or reject, with reasons and flags. It steers the loop but can never authorise an action.
VerdictDecision
¶
Bases: StrEnum
A verifier's answer: ACCEPT, REVISE or REJECT.
VerificationLoop
¶
Verifier
¶
Bases: Protocol
Judges a proposed final answer.
Its verdict steers the loop but can never authorise an action. A verifier that cannot be understood counts as a rejection.
VerifyRequest
dataclass
¶
What the verifier is given.
The goal, the proposed answer, the actions taken this step and the (untrusted) observations.
default_checkpointer
¶
A durable store: LangGraph's SQLite saver if installed, else the standard-library one.
The choice depends on what is installed, so pass an explicit store anywhere the two must agree. Both hold the same JSON and a run can be moved between them.
diff
¶
Compare two recordings step by step and return every divergence (empty when they match).
find_run
¶
The run id whose trace id is trace_id within one tenant (never across tenants).
replay
async
¶
Replay a recording through a fresh loop and report any divergence.