Inspector
The Inspector is a browser UI for looking at a running B4.run app's runtime
state. It ships as its own package, @b4run/inspector, and opens with
b4 inspect. The first panel is Memory, where you browse, search and govern
the app's long-term memory records.
LaunchingCopy link to section: Launching
b4 inspectThe CLI starts the inspector's server on 127.0.0.1 at a free port, prints the
URL and opens your browser. It takes these flags:
--cwd <path>: inspect a different app root (defaults to the current directory).--port <number>: bind to a stable localhost port instead of a free one.--env-file <path>: load a.envfile before resolving the store. It overridesb4.config.tsenvand the default./.env, the same precedence asb4 dev.
Apps scaffolded with create-b4-app ship the inspector as a
devDependency. In an existing app, install it once:
npm i -D @b4run/inspectorb4 inspect resolves the package from the app's own node_modules. If it's
missing, the command prints the install hint and exits.
Which store it inspectsCopy link to section: Which store it inspects
The inspector serves the app's live memory store. It loads your
b4.config.ts and uses config.memory.store just as the dev server does.
The default SQLite store, the pgvector backend
and custom MemoryStore implementations all work unchanged.
The inspector runs as a separate process, so two caveats apply:
- It constructs a second store instance from your config. For SQLite that's a second connection to the same database file. For Postgres it's a second connection pool. Both are safe, but count it against connection limits.
- The store must be constructible from config alone. If a store closes over live objects created elsewhere in your server process, the inspector can't re-create it.
The Memory panelCopy link to section: The Memory panel
- Browse and filter: every record across namespaces and statuses (not only candidates), with facet counts by status, kind, namespace and source type.
- Search: ranked search that matches recall. It runs the same IDF-weighted
keyword ranking as the agent's
recalltool. When your config declares a vector embedder and the provider key is available (for example via--env-file), it runs the same hybrid keyword + vector fusion. - Live refresh: lists and facet counts poll every 2 seconds while the tab is visible, so agent writes show up as they happen.
- Detail sheet: the full record (data, tags, confidence, source, supersession links) with the governance actions below.
- Approve: promotes a candidate with the same supersede-aware
reconciliation as
b4 memory approve. A contradicting active record with the same identity is superseded (history preserved), an identical one dedupes the candidate, and otherwise the candidate activates. When approving would supersede an active memory, the sheet shows a callout and the button reads Approve & supersede. - Reject / Forget: hard-delete a candidate or any record, each behind a confirmation prompt.
Timeline viewCopy link to section: Timeline view
With episodic memory enabled, the panel's
list/timeline toggle switches to a timeline of what the agent did: records
grouped by day, each row showing the time it happened, an outcome badge
(ok/error for auto-recorded runs, authored for agent-written episodes),
the episode summary, and the run duration. A window select (24h / 7d / 30d /
all) narrows the timeline, and the kind filter defaults to episodic there.
Clicking a row opens the same detail sheet as the list.
Like agent recall, the panel excludes expired episodes. Search always
excludes them, because it mirrors what the agent's recall can see. To debug
retention, the list API accepts includeExpired=1 to reveal rows that are past
their TTL but not yet pruned.
Security postureCopy link to section: Security posture
The inspector is a local development tool:
- The server binds to
127.0.0.1only, so it's never reachable from the network. - Every API route verifies the
Hostheader and rejects state-changing requests with a foreignOrigin. This protects against CSRF and DNS rebinding from other pages open in your browser. - Destructive actions (reject, forget) require an explicit confirmation in the UI.