soev for developers
soev-inspect

soev_inspect

Show what each model call of a thread received, replayed from a trace store.

The command soev-inspect is the main interface: it lists, exports and inspects threads, as text or in the browser. In Python, open a store by the same reference string as on the command line, and replay one thread. The replay builds each request again with the code in this process, and asks no model to reply. The view that it returns is JSON in an experimental format.

Stores

A reference string names a trace file, a directory of trace files, a SQLite file or a Postgres trace store.

opened

functionopened(ref) -> AbstractAsyncContextManager[TraceStore]

Open the store that ref names, for as long as the context lasts.

ref is a reference string, the same string that names a source on the command line:

  • postgresql://…?schema=NAME: a Postgres trace store, schema soev when none is named.
  • a path ending in .db, .sqlite or .sqlite3: a SQLite trace store, created when missing.
  • any other path: one trace file, or a directory of them with its subdirectories, read into a store in memory.

A Postgres store also takes postgres://. It needs the postgres extra of soev-inspect, and it creates no tables. In a directory, a .json file that is no trace file is skipped. A path that does not exist gives an empty store in memory, without an error. A change to a store in memory reaches no file.

paramrefstr

The reference string.

Returns

AbstractAsyncContextManager[TraceStore]

A context manager that gives the open store, and closes the store when the context ends.

Raises:

  • ValueError: ref names one file that is no trace file (pydantic.ValidationError is one), or a trace file whose log is not sealed.

Replay a thread

The replay gives the view of a thread: its events, and each model call with the request that today's code builds.

load_thread

functionload_threadasync (store, thread_id, *, agents, resources=…, model=None) -> Json

Read thread_id from store and return its view, every model call replayed.

The replay builds the graph of each turn with the code in this process, and rebuilds the request of each model call from the recorded events. It asks no model to reply. So the view shows what today's code sends, which differs from what was sent when the agent changed since the thread ran. The command soev-inspect and its page show the same view.

Example

from app.agents import AGENTS  # your mapping from each agent name to its Agent
from soev_inspect import load_thread, opened

async with opened("traces.db") as store:
    view = await load_thread(store, "thr-abc", agents=AGENTS)
paramstoreTraceStore

The trace store that holds the thread, for example from opened.

paramthread_idstr

The id of the thread.

paramagentsMapping[str, Agent[Any, Any]]

The agents by name. The thread is replayed with the agent that its Opened event names.

paramresourcesOfflineResources
= …

The resources of the agent for its build. The default gives None, for agents that build their graph without resources.

parammodelstr | None
= None

The name of a model. Each turn is then rebuilt as if its input had named this model, to show the request that the replay builds for that model. None rebuilds each turn with the model of its input.

Returns

Json

The view of the thread, in the experimental format that Json describes.

Raises:

  • LookupError: The store holds no event of the thread.
  • NotReplayableError: The thread has no Opened event that names its agent, or agents does not hold that agent.
  • soev_agents.runtime.UnknownEventTypeError: The thread holds an event of a type that its agent does not declare.
  • soev_agents.domain.UnknownElementTypeError: The thread holds an element of a class that its agent does not declare.

OfflineResources

type aliasOfflineResources = Callable[[Agent[Any, Any]], Any]

A function that returns the resources of one agent for a replay, which calls no store and no model.

load_thread calls it once with the agent of the thread, and gives the result to each build of that agent. An adapter from soev_agents.runtime.refusing fits each resource. A refusing model gives no request "as sent". To see that request, give a model adapter that implements soev_agents.ports.PreparesRequests: the replay asks it to prepare each request, never to reply.

Json

type aliasJson = dict[str, JsonValue]

A JSON object: the view of a thread that load_thread returns, or a part of that view.

The format of the view is experimental. Its keys can change in any release before a stable release. The page of soev-inspect serve and the --json output of the text commands read the same format.

The view has these keys:

  • thread_id and agent: the thread, and the name of the agent that opened it.
  • replayed_with: the code that did the replay. commit and dirty describe the git repository of the working directory, and framework is the version of soev-agents. commit and framework are null when they are not known.
  • events: each stored event of the thread in log order, with its id (stream:seq), its position in the log, and call: the index of the model call that the event records, from 0, or null. The image data of a tool result is replaced by its size.
  • calls: each model call, with its id, node, model, timing, usage, and same_request: whether the request that today's code builds has the recorded hash. built holds the request that today's code builds, compared with the previous call. sent holds the request that the model adapter prepares to send, compared with built, or null when the adapter cannot show it. unreplayable says why a call has no built request.

NotReplayableError

errorNotReplayableError

A thread that the given agents cannot replay.

load_thread raises it when the thread has no Opened event that names its agent, or when its agents argument does not hold that agent.

On this page