VORIM
We use cookies

We use cookies to analyze site traffic and improve your experience. You can choose to accept all cookies or only essential ones. See our Privacy Policy.

Payload privacy

Send a keyed digest of your prompt rather than the prompt. Commitments, no-payload mode, and what a counterparty can still verify without seeing your content.

Payload Privacy

Your prompts and model outputs never have to reach Vorim. The audit event carries a digest of them, computed in your process. This section is about making that a guarantee rather than a habit, and about the difference between a digest and a commitment.

Commit, don’t just hash

A bare SHA-256 of a prompt is not a commitment, it is a lookup key. Prompts are low-entropy and usually templated, so anyone holding the digest and the template recovers the content by trying candidates until a hash matches. That includes us, and anyone who obtains an export.

Use a keyed commitment for anything a person or a model wrote. The key stays in your process and is never sent. Keep hashPayload only for content that is already high-entropy, such as a file digest or a random identifier.

import { commitPayload, hashPayload } from '@vorim/sdk';

// The key lives in your secret store and is never sent to Vorim.
const key = process.env.VORIM_COMMITMENT_KEY!;

await vorim.emit({
  agent_id: agent.agent_id,
  event_type: 'tool_call',
  action: 'invoice.refund',
  result: 'success',
  input_hash: await commitPayload(prompt, key),      // hmac-sha256:...
  output_hash: await commitPayload(completion, key),
});
typescript
Rotating the key does not invalidate past events, so retain the key you used for as long as you might need to prove the events it covers. Scoping a key per tenant or per agent means disclosing one subset never opens the rest.

Disclose later, to whoever needs it

To prove that a specific prompt produced a specific audit record, hand the verifier the content and the key. They recompute and compare. Until then the record shows that an action happened and nothing about what was in it.

import { commitPayload } from '@vorim/sdk';

// The auditor has the event, the prompt, and the key. They recompute.
const recomputed = await commitPayload(disclosedPrompt, disclosedKey);
console.log(recomputed === event.input_hash);  // true
typescript

Refuse to send content at all

The hash fields were always the right place for content, but nothing enforced it, and metadata is a free-form object that a whole prompt fits into by accident. Turn the guard on and the SDK throws before anything leaves your process.

It rejects non-scalar metadata, metadata strings over the limit (256 characters by default), and any hash field that is not a well-formed digest, which is what catches a raw prompt passed to input_hash.

const vorim = createVorim({
  apiKey: process.env.VORIM_API_KEY!,
  noPayload: true,                       // or { maxMetadataChars: 1024 }
});

await vorim.emit({
  agent_id: agent.agent_id,
  event_type: 'tool_call',
  action: 'invoice.refund',
  result: 'success',
  metadata: { tool: 'stripe.refunds.create', attempt: 2 },   // ok
});

await vorim.emit({
  agent_id: agent.agent_id,
  event_type: 'tool_call',
  action: 'invoice.refund',
  result: 'success',
  metadata: { prompt: fullPrompt },                          // throws
});
// VorimError PAYLOAD_BLOCKED — nothing was sent
typescript
This is not the same as the Zero Data Retention setting in your dashboard. Zero Data Retention drops metadata when we persist it, by which point the content has crossed the network and passed through our process. This mode means it never left yours. Use both if you want both.
Action and resource are left alone. Both are short structural identifiers covered by the signature, so keep tool names in them and arguments out.

Referencing an event

Every emit returns a stable content digest alongside the event id. The digest is computed over exactly the bytes the signature covers, so you can recompute it yourself and get the same value, and hand it to a downstream evidence layer as a reference that does not depend on trusting either of us to compute it.

const { events } = await vorim.emit({ /* ... */ });
// events: [{ event_id: 'evt_...', digest: 'sha256:...' }]

// Recompute it yourself, offline, from the event you sent.
import { eventDigest } from '@vorim/sdk';
console.log(await eventDigest(sentEvent) === events[0].digest);  // true
typescript

The same value is what prev_event_hash references on the next event, so a hash-chained emitter is already producing these. It is a content digest rather than an identity: two byte-identical events share one, which is why the response carries the event id beside it.

Need Help?

Book a demo for a walkthrough, or contact us for support. For enterprise needs, reach out at sales@vorim.ai.