Skip to content
Français

Read execution journals

Record agent events and read the journal of a completed or failed dispatch.

Each dispatch records its events in a journal by default. Set logging.transporter to choose its storage location, then use readJournal() to inspect the recorded events after the run.

import { createLocalTransport, dispatch } from "@elie-laloum/outpost";
import { repository, sandboxProvider, coder } from "./outpost.config.ts";

export const transporter = createLocalTransport({
  directory: ".outpost/storage",
});
export const result = await dispatch({
  repository,
  sandboxProvider,
  agent: coder,
  brief: { text: "Describe the repository without changing it." },
  logging: { transporter },
});
import { reportValue } from "./reporter.ts";
import { result, transporter } from "./record-journal.ts";
import { readJournal } from "@elie-laloum/outpost";

if (result.logReference) {
  const events = await readJournal({
    transporter,
    reference: result.logReference,
  });
  reportValue(events.length);
  // Example output: 12
}

result.logReference points to the finished journal. Without logging, Outpost writes it to a local transport in <repository>/.outpost/storage. To keep journals elsewhere, pass another transport: see Where data lives and S3 and R2.

API reference: Logging.

Object options combine: { transporter, verbose: true, replayable: true }. A sandbox session takes logging once for all its dispatches, and each sandbox.dispatch() can override it.

readJournal() returns the events in the order they happened. Each entry is a plain object: the event fields with its kind, plus at, seq, source, scope and the dispatch label when you set one.

API reference: ReadJournalOptions.

Reading fails if the journal exceeds the configured limits; it does not return a truncated transcript.

import { createLocalTransport, readJournal } from "@elie-laloum/outpost";
import type { TransportReference } from "@elie-laloum/outpost";

declare const reference: TransportReference;

const events = await readJournal({
  transporter: createLocalTransport({ directory: ".outpost/storage" }),
  reference,
  maxEntries: 5_000,
  maxBytes: 8 * 1024 * 1024,
});

API reference: ObservationEvent and AgentObservation.

dispatch-finished carries the status (done, failed or cancelled), completed, the token usage, the branch and commits, and the error code and message on failure. operation events carry their durationMs.

The built-in harness emits model-request and model-response only on a verbose hub. To record full model exchanges, pass one with verbose logging:

import { createObservationHub, dispatch } from "@elie-laloum/outpost";
import { coder, repository, sandboxProvider } from "./outpost.config.ts";

const observation = createObservationHub({ verbose: true });
await dispatch({
  repository,
  sandboxProvider,
  agent: coder,
  brief: { text: "Describe the repository without changing it." },
  observation,
  logging: { verbose: true },
});
await observation.close();

logging: { replayable: true } stores each commit of the dispatch as a verified binary patch. createReplayAgent() then replays the journal without calling a model: see Replay without a model.

A failed or cancelled dispatch still closes its journal with dispatch-finished, including a failure during preparation. The error carries the reference: read it with recoveryDetails().

import { dispatch, recoveryDetails } from "@elie-laloum/outpost";
import { coder, repository, sandboxProvider } from "./outpost.config.ts";

try {
  await dispatch({
    repository,
    sandboxProvider,
    agent: coder,
    brief: { text: "Fix the failing tests and commit the fix." },
  });
} catch (error) {
  console.error(recoveryDetails(error)?.logReference);
  throw error;
}

Errors lists the other recovery details.

Journals stay in their transport until you remove them. A retention policy with the closed-logs scope deletes closed journals older than a given age: see Retention and cleanup.

  • A journal is written by an observation hub receiver. It shares the hub’s bounded queue (capacity, deliveryTimeoutMs): when its transport fails or falls behind, the journal can miss events, be disabled for the rest of the run or stay open, and the failure appears in result.observerErrors (in recoveryDetails(error) when the dispatch fails). readJournal() then returns the events written before the failure.
  • Journals hold prompts, agent messages and tool results, so they contain repository content. Store and share them like the code; replayable adds the patches of every commit.

API: Logging · readJournal · ReadJournalOptions · DispatchResult · recoveryDetails · createObservationHub.