Model integrations are easy to instrument badly.
Logging every prompt creates unnecessary data exposure. Logging only the model name leaves too little evidence when a production response needs investigation.
An execution receipt offers a middle path: preserve operational metadata without copying the full interaction into a general-purpose log.
What belongs in the receipt?
Useful fields include:
request and task identifiers;
prompt, policy, and schema versions;
endpoint alias;
start time and latency;
usage measurements;
validation outcome;
fallback or retry status.
Application request
↓
Redaction and classification
↓
Model endpoint
↓
Output validation
↓
Execution receipt store
Teams evaluating model endpoints for this architecture can place VectorEngine behind the same application-owned wrapper and receipt format.
Disclosure: this article includes an external referral link for readers who want to explore the platform.
TypeScript-style pseudocode
type Receipt = {
requestId: string;
task: string;
promptVersion: string;
endpointAlias: string;
startedAt: string;
latencyMs?: number;
contractPassed?: boolean;
fallbackUsed: boolean;
status: "started" | "completed" | "failed";
};
async function invokeWithReceipt(input: unknown, ctx: Context) {
const started = Date.now();
const receipt: Receipt = {
requestId: ctx.requestId,
task: ctx.task,
promptVersion: ctx.promptVersion,
endpointAlias: ctx.endpointAlias,
startedAt: new Date(started).toISOString(),
fallbackUsed: false,
status: "started"
};
try {
const result = await invokeEndpoint(input, ctx.endpointAlias);
receipt.latencyMs = Date.now() - started;
receipt.contractPassed = validateOutput(result);
receipt.status = "completed";
await appendReceipt(receipt);
return result;
} catch (error) {
receipt.latencyMs = Date.now() - started;
receipt.status = "failed";
await appendReceipt(receipt);
throw error;
}
}
This example intentionally excludes raw input and output. If investigation requires content access, store it under a separate retention and authorization policy rather than embedding it in every receipt.
Receipts should also be append-oriented and versioned. Editing old records in place makes later reconstruction harder.
The goal is modest: retain enough evidence to understand how a model-backed feature executed, while collecting no more content than the workflow requires.
Top comments (1)
The useful move here is narrowing the receipt to operational evidence instead of treating "observability" as license to dump prompts and outputs into a general-purpose log. Request IDs, schema versions, latency, validation outcome, fallback usage, and append-only receipts are enough to reconstruct most production failures without turning tracing into a content-retention problem. I also like the point that content access, when it is necessary, should live under a different policy boundary entirely. This is very aligned with why I care about tools like agent-inspect: the value is not just more telemetry, it is having a human-debuggable evidence chain for model-backed features. Curious whether you have experimented with a receipt schema that can stitch together multi-tool sessions, not just single endpoint calls.