developer portal
build on the stream.
Everything in spectroscope hangs off one idea: an agent run is a typed stream of RunEvents, and that stream is at once the API, the storage format, the UI protocol, and the audit log. This page gets you from zero to reading the stream.
the complete user guide
Every surface in one book, from the thirty-second start to the fleet reference. Every screenshot is a real capture of the running app, reshot per release in both editions.
quickstart
an agent in five lines
The facade below is frozen: it already runs in the codebase exactly as written, and it is pinned by tests so it stays this way. v0.1.0 ships under the Maven coordinates shown; the artifact is not on Maven Central yet. The source is public at github.com/spectroscope/spectroscope.
var agent = Spectro.agent()
.model(Anthropic.opus())
.tools(Tools.readFile(), Tools.runCommand())
.workspace(Path.of("/tmp/scratch"));
for (RunEvent event : agent.run("Write hello.py and run it")) {
System.out.println(event); // the stream IS the observability
}
agent = (Spectro.agent()
.model(Anthropic.opus())
.tools(Tools.read_file(), Tools.run_command())
.workspace("/tmp/scratch"))
for event in agent.run("Write hello.py and run it"):
print(event) # the stream IS the observability
the Python port is in design: the JSONL wire is the contract, so the stream reads the same in both
maven
<dependency>
<groupId>dev.spectroscope</groupId>
<artifactId>spectro-core</artifactId>
<version>0.1.0</version>
</dependency>
cli
$ spectro run "write hello.py and run it"
$ spectro replay run.jsonl # byte for byte
$ spectro web # the whole cockpit
$ spectro doctor # checks your setup
plain Java 21 on virtual threads · no reactive DSL · no container · tools sit behind a permission gate, because tool inputs are model output and therefore untrusted
the contract
one JSONL file is the whole truth
A finished run lands as newline-delimited JSON: ordered, complete, byte-stable. The wire format is the compatibility contract of the project, so a trace recorded on one machine replays on any other. These lines are abridged from the bundled review fan-out scenario:
{"type":"run_start","runId":"fanout-main","agentId":"main","prompt":"Review the open PR…"}
{"type":"thinking_delta","agentId":"main","text":"I fan out into three parallel reviewers."}
{"type":"tool_call","agentId":"main","name":"review","input":{"areas":["bugs","perf","security"]}}
{"type":"agent_spawn","agentId":"bugs","parentId":"main","task":"Find bugs in the diff"}
watching is passive: the web views, the explain layer and every exporter only read the stream; the one write path back into a live run is the permission gate, and that answer comes from you
the modules
small parts on one backbone
The RunEvent stream is the only contract between them.
spectro-core
The harness SDK: agents, tools, the permission gate, the typed event stream.
spectro-cli
The spectro launcher: run, replay, doctor.
spectro-server + web
The local cockpit: chat, Spectrum, Trace, graph, text feed and the Lab over one WebSocket.
spectro-orchestrator
Small agents on one bus, exchanging task, status and result messages.
spectro-explain
The why layer: gate explanations and causal chains, computed from the stream.
spectro-mcp-notes
A worked MCP server example to copy from.
the stack
runs on Spring. almost nothing else.
spectro-core is a plain Java 21 library: you instantiate agents with
new, and Spring appears in the core only as its HTTP client.
The server face is one ordinary Spring Boot app that serves the web UI
from its own jar. The full dependency list is Jackson, Spring's web
client, the Anthropic SDK, a cron parser and slf4j; the CLI adds picocli,
the faces add logback. There is no agent framework underneath and no
vector database to feed.
An observability tool should be observable itself: five small Gradle modules, one typed stream, and every run on disk as JSONL you can open in an editor.
spectro web
the cockpit, in one capture
This is the Trace tab replaying a bundled demo scenario, with the reasoning lens active: thinking events in the foreground, everything else dimmed, and each thought pinned to the tool call that followed it. Read the thinking for what it is: the model's self-report, not a window into the weights. Scenarios are scripted runs, so you can explore every surface of the app before you connect a model.
more captures from the same scripted scenario: spectroscope.ai
status
where the project stands
spectroscope is pre-release. The harness, the CLI, the web cockpit and the scenario player exist and are under test (532 JUnit and 310 vitest checks at the current baseline); the the source is public on GitHub today; the Maven artifact lands with v0.1.0. Everything ships under the MIT license, which permits commercial use and closed-source forks.