research-agent

command
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

README

research-agent — LoopKit Flagship Durability Demo

A multi-phase research agent that proves event-log durability across SIGKILL: the SQLite store survives hard process termination; Resume folds the log and finishes exactly where execution stopped.

Loop phases

The agent runs exactly 5 iterations, one tool call per iteration. Returning (state, nil, nil) on KindToolCalled ends the iteration — the runner writes a new IterationStarted event, creating a resume checkpoint between phases.

Iteration Phase Action
1 search web_search — discover result URLs
2 fetch1 fetch_page — read result #1
3 fetch2 fetch_page — read result #2
4 synthesize synthesize_findings — combine into summary
5 done action.Finish — emit ResearchResult

All tools carry Semantics: action.Idempotent, so Resume safely re-executes any tool whose result was not yet persisted before the kill.

CLI

# Default: run to Completion using an in-memory store, print findings, exit 0.
go run ./examples/research-agent/

# Persistent run — write the loop ID to an idfile, use a SQLite store.
go run ./examples/research-agent/ \
    --topic "Go concurrency" \
    --store sqlite:///tmp/research.db \
    --idfile /tmp/loop.id

# Resume a previously interrupted or crashed loop.
go run ./examples/research-agent/ \
    --resume <loopID> \
    --store sqlite:///tmp/research.db
Flags
Flag Default Description
--topic machine learning Research topic
--store (in-memory) Store DSN: sqlite:///path or empty for memory
--resume (empty) Loop ID to resume; skips Start if set
--idfile (empty) Path to write the loop ID as soon as it exists
Environment
Variable Default Description
RESEARCH_TOOL_SLEEP_MS 0 Sleep per fake tool call (ms). Set to 150 to make
SIGKILL land mid-run in demo.sh.

Kill/Resume demo

demo.sh is a self-contained POSIX sh script that proves durability end-to-end:

sh examples/research-agent/demo.sh
# or
LOOPKIT_TOPIC="quantum computing" sh examples/research-agent/demo.sh

What it does:

  1. Builds the binary.
  2. Launches it with RESEARCH_TOOL_SLEEP_MS=150 against a temp SQLite store and --idfile, so tool calls take ~150ms each.
  3. Polls the idfile until the loop ID appears (written as soon as LoopStarted lands in SQLite, before any tool calls run).
  4. Sleeps 400ms more (mid-run), then kill -9 the process.
  5. Reads the loop ID from the idfile.
  6. Relaunches with --resume <loopID> --store sqlite://<path>.
  7. Asserts the output contains "Completed" — exits 1 otherwise.
  8. Cleans up temp files.

What it proves:

  • The SQLite event log is durable across SIGKILL (no buffering, fsync on append).
  • Resume folds the existing event log (replaying already-persisted events without re-executing their effects) and continues from the last checkpoint.
  • Each iteration boundary is a natural resume point — no explicit checkpointing needed in the Transition function.

Tests

go test -race -count=1 ./examples/research-agent/
Test What it checks
TestResearchAgentCompletes Default run -> outcome.Completed with >=5 findings, 5 iterations
TestResearchAgentPhaseOrder Findings in correct phase order (search->fetch->synth->conclusion)
TestResearchAgentResume Crash-store simulation -> Resume -> Completed + contiguous log

TestResearchAgentResume uses a crashAfterNToolCalled store wrapper that returns an error after the first KindToolCalled event is written, leaving the loop mid-run. A second runner sharing the same (non-crashing) store calls Resume and asserts Completed with a contiguous event log. No subprocesses or SIGKILL are used in the Go test (flaky); the SIGKILL proof lives in demo.sh.

Documentation

Overview

Command research-agent is the LoopKit flagship durability demo.

It runs a multi-phase research agent (search → fetch1 → fetch2 → synthesize → finish) where each phase executes in its own iteration. The SQLite event log persists across process restarts, enabling genuine crash-resume without losing any completed work.

Loop phases (one tool call per iteration)

  1. search — web_search for the topic
  2. fetch1 — fetch_page on the first result URL
  3. fetch2 — fetch_page on the second result URL
  4. synthesize — synthesize_findings (combines page content into a report)
  5. finish — action.Finish emits the final ResearchResult

Usage

go run ./examples/research-agent/
go run ./examples/research-agent/ --topic "quantum computing"
go run ./examples/research-agent/ --store sqlite:///tmp/r.db --idfile /tmp/loop.id
go run ./examples/research-agent/ --resume <loopID> --store sqlite:///tmp/r.db

Environment

RESEARCH_TOOL_SLEEP_MS=150   sleep this many ms per fake tool call (default 0)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL