DEV Community

Akshat Joshi
Akshat Joshi

Posted on

Your prompt needs an SBOM

Your prompt needs an SBOM

Draft — publish on dev.to + personal blog, cross-post to Medium. Add the demo GIF after the first section.


Ask any team running AI in production a simple question: what exactly did your model see?

Not "what was the user's question." What was the full context — the retrieved chunks, the agent memory, the tool outputs, the system prompt, the ticket text that got pasted in. The complete input that produced the output you're now trying to explain.

Almost nobody can answer. The context was assembled at runtime from half a dozen sources, concatenated into a string, sent to the model, and discarded. The provenance died at assembly time.

We've solved this problem before

Software had the same blind spot with binaries. A deployed artifact was an opaque blob of vendored dependencies until supply-chain attacks — Heartbleed, log4shell, SolarWinds — made "what's inside this thing?" a question with regulatory force behind it. The answer was the SBOM: a machine-readable bill of materials for every build. Boring, structured, and now mandated in US federal procurement.

AI context is today where dependencies were in 2010. Every prompt is a build artifact assembled from unvetted inputs, and there is no manifest.

Consider what flows into a single agent's context window: RAG chunks from a vector store, conversation memory, MCP tool responses, file contents, other agents' outputs. Each has different ownership, sensitivity, and trustworthiness. Prompt injection via tool output is a top-ten LLM risk precisely because nobody inspects that boundary. When something goes wrong — a leak, a hallucinated policy, an agent following instructions that arrived inside a webpage — the investigation starts with reconstructing what the model saw, from logs that were never designed to answer that question.

And the regulatory clock is running: the EU AI Act's record-keeping obligations for high-risk systems require demonstrating what your AI processed. A concatenated string in a debug log does not demonstrate that.

A bill of materials for every prompt

CBOM — the Context Bill of Materials — is an open spec that gives every model call a manifest: for each segment of context, its source URI, a content hash, the ordered list of transforms applied (redactions, truncations, summarizations — each hash-chained), a sensitivity label, and optionally a signature.

One deliberate design choice does most of the work: manifests contain hashes and metadata, never content. A CBOM manifest can't leak what it describes. That's what makes it safe to log every call, retain for years, and hand to an auditor — even when the context itself was full of PII.

The reference SDK is three lines around your existing code:

import contextbom as cbom

ctx = cbom.Context()
ticket = ctx.add(fetch_ticket(id), source="https://jira.co/T-42",
                 sensitivity="pii", transforms=[cbom.redact_pii])
# ...build your prompt, call your model as usual...
ctx.manifest.to_json("call.cbom.json")
Enter fullscreen mode Exit fullscreen mode

And cbom view renders any logged call as a color-coded breakdown — which segment came from where, what was redacted, whether the hash chain verifies.

What CBOM is not

It's not a gateway, a proxy, an agent framework, or a hosted service. There's nothing to deploy. It's a JSON format plus a small library — deliberately, because the goal isn't to be another tool in the stack. It's to be the format the existing stack emits.

Gateways, memory layers, RAG frameworks, and MCP middleware all touch context assembly, and some already produce their own ad-hoc audit records. Each has its own format, which means none of them compose. That's the moment a neutral spec is useful — the same moment logging libraries converged on OpenTelemetry.

The spec (v0.1, deliberately tiny, breaking changes welcome) and reference implementation are here: github.com/contextbom/contextbom. If you build anything that assembles LLM context, the RFC thread is open — I'd like to know what would make emitting CBOM trivial for you.

Every token that enters a model should have a verifiable origin. That shouldn't be a feature. It should be a default.

Top comments (0)