MCP Observability: The Write Ledger That Turns Agent Actions Into an Audit Trail
MCP Observability: The Write Ledger That Turns Agent Actions Into an Audit Trail
MCP made it trivial to give an AI agent real hands. Connect a server, and the model can create a Google Ads campaign, move a budget, build a Meta audience, send a Mailchimp blast — autonomously, in the same loop it uses to read your data.
That's the whole promise. It's also the whole problem.
Because the moment an agent can write to your live ad accounts and email lists, a question shows up that no chat transcript answers cleanly: when something changed, who changed it, what exactly did they send, and can you prove it three months from now in an audit?
If you're a solo founder, you can squint at your chat history. If you're an enterprise — or anyone who answers to a security team, a compliance officer, or a client whose ad account you're touching — "squint at the chat history" is not an answer. It's a finding.
Today we're shipping the answer: the Cogny MCP Write Ledger. When you enable it, every write tool call your agents make — through the public MCP endpoint, the in-app chat agent, and the ticket-execution agents — is streamed as an immutable audit row into a table in your own BigQuery warehouse. Successes and failures both. Inputs and responses both.
TL;DR
- The problem with raw "MCPs in the wild": a third-party MCP server connected point-to-point gives an agent write access with no central record of what it did. Each server logs differently, or not at all. When a budget triples overnight, there's no ledger to query.
- The Write Ledger captures every mutation (
create_*,update_*,delete_*,send_*,publish_*, …) across all three Cogny agent surfaces into one consistent, schema'd audit table. - Failures are logged too — with the error message and the parameters that were attempted — so you can trace what an agent tried to do, not just what stuck.
- It lands in your warehouse, not ours. Rows go to
<dataset>.mcp_write_ledgerin your GCP project (EU region, day-partitioned). Cogny never keeps a second copy. Query it with SQL like any other table. - Reads are never recorded.
list/get/search/inspectstay out of the ledger, so it's a clean record of changes, not noise. - Strictly opt-in, zero overhead when off. Default false; a disabled warehouse costs one in-memory lookup per call.
- This is the difference between an MCP you can demo and an MCP you can put in front of an enterprise security review.
"MCPs in the wild" are an observability black hole
Here's the architecture most teams reach for first. Find an MCP server for the tool you want — Google Ads, a CRM, an email platform — and wire it directly into your agent. Point-to-point. It works in the demo, the tools show up, the agent starts doing things.
Now ask the operational questions:
- An ad budget went from $500/day to $5,000/day at 2am. Which agent run did that? On whose authority? What was the exact parameter payload?
- A customer says they got an email they never opted into. Did one of your agents send it? Through which tool, with what content?
- Your SOC 2 auditor asks for "a record of all automated changes to production marketing systems over the last quarter." Can you produce it?
With raw MCP servers, the honest answers are maybe, I'd have to dig, and no. Each server has its own logging (or none). There's no single place that says "a write happened here." The agent's chat transcript is not an audit log — it's a conversation, often summarized, frequently truncated, and stored wherever your AI client happens to keep it.
This isn't a knock on MCP. It's a knock on connecting MCP servers with no observability layer in between. The protocol gives you reach. It doesn't give you a ledger.
The gap isn't "can the agent do the thing." It's "can you prove what the agent did, after the fact, to someone who wasn't in the room."
What Cogny does differently: one proxy, one ledger
Cogny doesn't hand agents raw point-to-point connections. Every tool call — whether it comes from an external agent over the public MCP endpoint, from the in-app chat, or from a scheduled ticket-execution run — flows through Cogny's proxy layer. That single choke point is what makes a unified ledger possible.
When the Write Ledger is on, the same function records every write, regardless of where it originated. Three sources, one consistent schema:
| Source | What it is | What gets traced |
|---|---|---|
external_mcp | An outside agent calling Cogny's MCP endpoint | The user who authorised the OAuth key — or the API key id, for headless cogny_lite_* agents |
chat_agent | The in-app report-builder / chat agent | The user who started the thread, plus the thread_id |
ticket_agent | Ticket-execution & analysis agents (scheduled or /Run Now) | The executing user, plus ticket_id and run_id |
Raw MCPs give you N servers with N logging conventions and N blind spots. The proxy model gives you one normalized record of every mutation, no matter which surface or which underlying integration produced it.
What a ledger row actually contains
Each write produces one row. The schema is deliberately boring — boring is what you want in an audit table:
SELECT
event_ts, -- when (UTC, day-partitioned)
source, -- external_mcp | chat_agent | ticket_agent
actor_type, -- user | api_key | system
actor_user_id, -- who authorised it
mcp_server, -- e.g. Google_Ads
tool_name, -- e.g. create_campaign
status, -- success | error
error_message, -- the failure reason, if it failed
duration_ms, -- how long the tool took
input_json, -- the full parameters the agent sent
response_json -- the response (null on error)
FROM cogny_audit.mcp_write_ledger
WHERE DATE(event_ts) >= CURRENT_DATE() - 7
AND status = 'error'
ORDER BY event_ts DESC;
That query — "show me every write my agents attempted and failed in the last week, with the parameters they tried" — is the kind of thing that's a one-liner with a ledger and effectively impossible without one.
A few design decisions worth calling out, because they're what make this trustworthy rather than decorative:
Failures are first-class. A failed create_campaign is often more interesting than a successful one — it's where an agent tried something that didn't stick, hit a permission wall, or sent a malformed payload. The ledger captures failed writes with the error message and the attempted input, so a partial or rejected change leaves a trace instead of vanishing.
Reads are excluded on purpose. Classification happens synchronously before any I/O: only explicit write prefixes (create, update, delete, send, publish, pause, disable, and friends) are recorded. list_campaigns, get_insights, execute_bigquery_sql — all the read traffic — never touch the ledger. The result is a high signal-to-noise record of changes, not a firehose of every query.
Inputs and responses are captured, with sane caps. You see what the agent sent and what came back, each capped per row so a runaway payload can't bloat your table.
Your warehouse, not ours
This is the part that matters most for anyone with a compliance posture, and it's the part that's easy to get wrong.
The ledger does not land in a Cogny-owned database that you have to file a support ticket to read. It lands in your own BigQuery project — the same warehouse Cogny already queries on your behalf — at <dataset>.mcp_write_ledger (default dataset cogny_audit, EU region, partitioned by day on event_ts). The table auto-creates on the first write after you enable the feature.
That means:
- Cogny never holds a second copy of your audit trail. The system of record is in infrastructure you own and control.
- You query it with your own tools — BigQuery console, Looker, dbt, a scheduled SQL export, whatever your data team already uses. It's just a table.
- Your retention and access policies apply automatically, because it's your project. No new vendor to add to the data-processing addendum for the audit log itself.
- It's tamper-evident in your environment. You control who can write to and delete from the dataset.
For a regulated team, "the audit log lives in our warehouse, under our IAM, in our region" is the difference between a feature they can adopt and one legal vetoes.
Turning it on
It's a single toggle in Settings → MCP Write Ledger. Off by default — the feature is strictly opt-in, and a disabled warehouse pays nothing beyond one cached config lookup per call.
When you flip it on, the destination table is created in your warehouse's GCP project on the first write. From there, every successful and failed write tool call is streamed in, fire-and-forget. (Audit logging is wrapped so it can never break the tool call it's observing — if a ledger insert hiccups, the underlying campaign-create still goes through, and the failure is warned, not raised.)
One caveat the UI is upfront about: if your warehouse doesn't have a BigQuery project provisioned yet, nothing is written until it does. The ledger writes to your infrastructure, so that infrastructure has to exist.
Why this is the enterprise unlock
The conversation about agentic marketing has been stuck on capability — can the agent do the thing? That question is basically settled. With MCP and a decent model, the agent can do the thing.
The question that actually gates enterprise adoption is the one after that: can you operate an autonomous agent that writes to production systems, and stand behind it? That requires:
- A record of every change, independent of the chat transcript.
- Attribution — which agent, which run, on whose authority.
- Failure visibility, not just success theater.
- The record living somewhere you own and govern.
"MCPs in the wild" — raw servers wired point-to-point — give you the capability and none of the accountability. The Cogny Write Ledger is the accountability layer that makes the capability safe to actually use at scale. It's the same reason you wouldn't run a database in production without an audit log, or deploy code without a commit history. Reach without a record is a liability; reach with a ledger is leverage.
If you're evaluating MCP for a team where "who changed what" has to have an answer, that's the bar. Cogny clears it — and writes the proof into a table you own.
Want to see the ledger in your own warehouse? Start with Cogny, connect a channel, and enable Settings → MCP Write Ledger. The first agent write lands as an audit row before your next stand-up. For the broader picture on why we proxy MCP instead of handing out raw connections, see MCP vs. marketing automation and the Cogny CLI.