Prompt & Response Data Security
Control what AI prompt and response content the SDK captures, mask sensitive fields before it's recorded, and use the SDK's AES-256-GCM encryption utility for your own captured payloads.
Prompt & Response Data Security
LLM prompts and responses can carry PII, business logic, or confidential documents fed into the context window. This page covers the two tools the SDK gives you to control that: capture toggles/masking in config, and an AES-256-GCM encryption utility you can use for content you capture yourself.
For the AI span attributes recorded on every call (tokens, cost, model, tool calls), see AI Observability — this page is specifically about the prompt/response content and how to keep it safe.
Capture toggles
ai.capturePrompts and ai.captureResponses control whether prompt/response text is captured at all, set globally in your config or per-client when you call wrapAI():
// Global — applies to every wrapped AI client
createSdk({
ai: {
capturePrompts: true,
captureResponses: true,
},
});
// Per-client override — useful when one client handles more sensitive
// content than others (e.g. a support bot vs. an internal tools agent)
const supportBot = sdk.wrapAI(new OpenAI(), {
captureInput: false, // this client's prompts are never captured
captureOutput: true,
});Set capturePrompts: false globally if your prompts routinely contain content you can't retain — the SDK will still capture everything else about the call (model, tokens, cost, latency, finish reason), just not the text itself.
Masking specific fields
ai.maskFields replaces named fields in captured content with [MASKED] before it's recorded, wherever they appear in the prompt/response text:
createSdk({
ai: {
maskFields: ['password', 'ssn', 'card_number', 'api_key'],
},
});Truncation
ai.maxContentLength (default 10000 characters) caps how much of a single prompt or response is captured — content beyond the limit is truncated with a ... suffix rather than dropped outright.
createSdk({
ai: { maxContentLength: 5000 },
});The encryption utility
The SDK exports PayloadEncryptor — an AES-256-GCM implementation built specifically for AI prompt/response content, with no dependencies beyond Node's built-in crypto module. It's available for you to use directly if you're building your own capture or export pipeline around the SDK:
const { createEncryptor } = require('@trasys/sdk');
// createEncryptor returns null if no key is given — check before using
const encryptor = createEncryptor(process.env.TRASYS_ENCRYPTION_KEY);
if (encryptor) {
const encrypted = encryptor.encrypt({
prompt: 'What is our refund policy for enterprise customers?',
response: 'Enterprise refunds are processed within...',
model: 'gpt-4o',
provider: 'openai',
traceId: currentTraceId,
});
// encrypted.data — base64(iv[12] || authTag[16] || ciphertext)
// encrypted.keyId — SHA-256 fingerprint of the key used (first 16 hex chars),
// lets you identify which key encrypted a payload without storing the key itself
}Key format: either a 64-character hex string, or a raw 32-byte Buffer. A hex string is hashed with SHA-256 to derive a consistent 32-byte key — you don't need to generate a key that's exactly 32 bytes yourself.
maskFields() — string-level redaction
A second, string-based masking method separate from the ai.maskFields config option above — useful if you're calling the encryptor directly and want to redact before encrypting:
const redacted = encryptor.maskFields(
'{"ssn": "123-45-6789", "note": "customer ssn=987-65-4321 on file"}',
['ssn'],
);
// → {"ssn": "[redacted]", "note": "customer ssn=[redacted] on file"}It matches both "field":"value" JSON-style pairs and field=value form-encoded pairs.
truncate()
encryptor.truncate(longText, 500);
// → first 500 chars + "... [truncated 1240 chars]"Decrypting
Decryption exists on the same class — mainly relevant if you're building tooling that needs to read back content your own code encrypted:
const original = encryptor.decrypt(encrypted);
// → { prompt, response, model, provider, traceId }PayloadEncryptor is a general-purpose utility exported for your own use — it is not something you need to call yourself for the SDK's own AI instrumentation to function. See AI Observability for how the SDK's built-in prompt/response capture behaves.
Next steps
- AI Observability — wrapping AI clients and what's captured on every call
- Database Instrumentation — the equivalent masking mechanism for SQL query values
- SDK Error Reference — what happens when the SDK can't validate your API key
AI Observability
Trace every LLM call, model, tokens, cost, prompts, responses, tool calls, across OpenAI, Anthropic, Gemini, Groq, Mistral, Cohere, and Ollama via sdk.wrapAI.
Custom Metrics
Record custom counters, gauges, and histograms with the monitor object — every call is automatically tagged with the active trace, user, and tenant ID.

