What leaves your process.
Every field the SDK transmits, and every field it doesn't. Read directly from packages/nextjs/index.ts and the routes that receive it — not summarized, not simplified.
Leaves
| Field | Type | Purpose |
|---|---|---|
| prompt_fingerprint | string, 64-char hex | SHA-256 of your prompt text, computed in your process before anything is sent. Used for loop detection. |
| estimated_tokens / actual_tokens / input_token_count / output_token_count | integers | Token counts, before and after the call. Used to compute cost and to measure context growth. |
| model | string | The model identifier you pass, e.g. "gpt-4o". Used to price the step. |
| tool_name | string | The name of the tool a step calls. Checked against the run's allowlist. |
| mutation_class | "read_only" | "reversible" | "destructive" | How destructive a step is. Checked against the run's ceiling. |
| step_type | "llm" | "tool" | "custom" | What kind of step this is. |
| is_retry / completion_status | boolean / enum | Whether a step is a retry, and how it finished. Optional telemetry — never a governance input. |
| budget ceiling, step cap, timeout, loop threshold | numbers | The boundary you declare in beginRun — your own limits, not a measurement of anything. |
| allowed_tools / max_mutation_class / strict_scope | string[] / enum / boolean | The tool allowlist and write ceiling you declare for the run. |
| run id | string | The id Thskyshield issues at beginRun, included in the URL of every later call for that run. You may also send your own external_run_id to correlate it with your logs. |
| agent_name / task_type / session_id / environment | strings, optional | Labels you choose, capped at 128 characters. Never required, never inferred. |
| request_id | string | Correlates an afterStep call back to the beforeStep call it's settling. |
metadata — An open field on beginRun. Its content isn't inspected or shaped by us — whatever you put in it is stored as you sent it — but its shape is restricted and validated in the SDK before transmission. Don't put prompt content in it.
Never leaves
| Field | Why not |
|---|---|
| Prompt text | Only prompt_fingerprint (a hash) is ever sent. The text it was computed from never is. |
| Completion text | afterStep sends token counts and a completion status. Never the response content. |
| Tool arguments | tool_name is sent. What you called it with is not. |
| Tool results | Not sent at any point in the run lifecycle. |
| Retrieved documents | No field carries document or context content. |
| System prompts | No field carries system-prompt content. |
| Your LLM provider's API keys | Thskyshield doesn't proxy your model calls — it sits beside them — so it never sees the credentials you use to make them. |
Metadata: the one field you control.
metadata is transmitted verbatim, restricted to flat key-value identifiers, maximum 32 keys, 256 characters per value, enforced in the SDK before transmission. We cannot inspect meaning — keep it to identifiers, not content.
Why
OpenTelemetry's GenAI semantic conventions recommend that request and response content — prompts, completions — not be captured automatically, because that content routinely carries sensitive information the instrumenting party never asked to hold. This follows the same principle. It isn't an option you can turn off; the code to send that content doesn't exist.
How to verify
The SDK is MIT-licensed and published unminified to npm. Install it, open node_modules/@thsky-21/thskyshield/dist/index.js, and grep for fetch. Every request body on this page is a JSON.stringify a few lines below one of those calls. Count the fields yourself.
What we cannot do
Because we never hold your prompt or completion content, we cannot reconstruct a prompt from what we store — there is nothing in our database to reconstruct it from. The same is true for anyone who compromises us. A breach of Thskyshield exposes fingerprints, token counts, and model names. It does not expose what your agents said or were told.
Questions about this page → contact us