Guide · Journal and assertions
AvailableLast verified
Know exactly which fixture answered
Every LLM request is written to a short-lived journal: the normalized request, the matched fixture, chaos and VCR decisions, the rendered answer, and timing. Tests assert against the journal instead of guessing from response text.
In this guide
- What an entry records
- Read the journal from any surface
- Assert matches in tests
- Retention and redaction
Prerequisites
- An LLM DotMock workspace, or a local dotmock.yaml served by dotmock serve
- The workspace ID in $API_ID and its runtime URL in $MOCK_URL (SDK base URL $MOCK_URL/v1 for OpenAI-compatible clients)
On this page
What an entry records
Each entry has the request's id, timestamp (ms), method, path, provider, endpoint, model, matched flag, session, seed, redacted headers, and body. The response part records status, fixtureId, fixtureName, chaosAction, vcrProxied or vcrReplayed, durationMs, stream, and the rendered content, reasoning, toolCalls, finishReason, usage, or error.
{
"id": "req_01J…",
"timestamp": 1758787200000,
"method": "POST",
"path": "/v1/chat/completions",
"provider": "openai",
"model": "gpt-4o-mini",
"matched": true,
"session": "test-42",
"seed": 1234,
"headers": { "authorization": "[REDACTED]", "content-type": "application/json" },
"body": { "model": "gpt-4o-mini", "messages": [{ "role": "user", "content": "hello" }] },
"response": {
"status": 200,
"fixtureId": "greeting",
"fixtureName": "greeting",
"durationMs": 3,
"content": "Hello!",
"finishReason": "stop"
}
}Read the journal from any surface
The workspace's Inspect view shows the same entries with the full request and response. For automation, filter by fixture, match status, provider, session, or time.
- Dashboard API — GET /mock-apis/$API_ID/llm-fixtures/journal?limit=50&fixtureId=&fixtureName=&matched=&provider=&session=&since=, and DELETE to clear it
- CLI — dotmock llm journal $API_ID [--session id] [--fixture name] [--limit 50] [--follow] [--local]
- MCP — get_llm_journal with apiId, limit (1–500), fixtureId, fixtureName, matched, provider, session, since, and includePayloads
- Local server — GET /__dotmock/journal?api=<subdomain>&limit=100&session=<id> (limit up to 1000)
dotmock llm journal $API_ID --session test-42 --follow
dotmock llm journal assistant --local --fixture greetingAssert fixture matches in tests
Assertions on the journal prove behavior the response alone cannot: that a tool round trip made two calls, that a retry happened after a 429, or that no request fell through to the catch-all. Reset between tests so each test sees only its own entries.
import { expectFixtureMatched, getJournal, resetDotmock } from "@dotmock/cli/testing";
beforeEach(() => resetDotmock());
it("retries after a rate limit", async () => {
await runAgent("summarize the ticket");
await expectFixtureMatched("rate-limited-once", { times: 1 });
await expectFixtureMatched("summary", { times: 1 });
const unmatched = (await getJournal()).filter((e) => !e.matched);
expect(unmatched).toHaveLength(0);
});def test_tool_round_trip(dotmock):
run_agent("weather in Paris?")
dotmock.assert_fixture_matched("weather-tool-call", times=2)
assert all(e["matched"] for e in dotmock.journal())Retention and redaction
Hosted journals keep the most recent 1,000 entries per API for one hour in Redis. The local server keeps them in memory; POST /__dotmock/reset clears counters and the journal for the API, while a reset scoped to one session clears only that session's counters.
Authorization, proxy-authorization, x-api-key, api-key, x-goog-api-key, cookie, x-internal-token, and x-amz-security-token headers are redacted. Request bodies over 64 KB keep a 4 KB preview and rendered content is capped at 4 KB.