20 maggio 2026 · 5 min di lettura · Cyril team
Every record explains itself: the ai_context serializer
Cyril gives every entity an ai_context serializer — a deterministic, schema-aware view built for the model, not the database. It's the unglamorous core of what makes AI grounding actually work.
The exciting part of AI-native software is the agent doing something useful. The part that actually makes it work is boring: how a record describes itself to a model.
Get that wrong and every downstream demo is built on sand. Get it right and the agent stops guessing.
Raw rows are the wrong input
A database row is built for the database. It has foreign keys, status enums, nullable columns, internal flags, and timestamps in UTC. Hand that to a model and you've asked it to do two jobs at once: reconstruct what the record means, and then reason about it.
It will do the first job badly. status: 3 means nothing without the lookup table. A null in closed_at could mean "still open" or "never tracked." A foreign key is a number the model can't follow. So the model invents the meaning it needs — confidently — and the error compounds through every step that follows.
The fix isn't a bigger model. It's giving the model the right input.
What an ai_context serializer is
In Cyril, every entity — an account, a deal, a project, a ticket, an invoice — exposes an ai_context serializer. It's a single method that returns a deterministic, schema-aware view of the record built specifically for AI grounding.
That view does the interpretation the model shouldn't have to:
- Enums are resolved to their human meaning —
status: 3becomes"stage: negotiation". - Related counts are folded in — an account carries its open-ticket count, active-project status, and outstanding-invoice state, because that's what a question about the account will need.
- Internal-only fields are stripped — the model never sees row IDs, soft-delete flags, or tenant plumbing.
- The shape is stable — the same record produces the same context every time, so prompts are cacheable and behaviour is reproducible.
It is, deliberately, not the API response and not the database row. It's a third representation whose only audience is a model.
Why "mandatory on every entity" is the whole point
It would be easy to write an ai_context serializer for the three entities a launch demo touches. That's the trap. The value of a single data graph is that a question can cross any boundary — "which at-risk accounts also have a late project and an unpaid invoice?" only works if accounts, projects, and invoices all explain themselves the same way.
So in Cyril the serializer is a requirement, not a feature. A new entity isn't done until it has one. The test patterns check for it. That discipline is unglamorous and it's exactly what lets an agent traverse the platform without hitting a record it can't read.
Determinism is a security property too
Because the serializer is the only AI-facing view, it's also the place we control exposure. Field-level decisions about what an agent may see live in one auditable spot per entity, scoped by org_id like every other query. There's no separate "AI export" path quietly widening the blast radius — the same serializer that grounds the model is the same boundary that limits it.
What it buys you
- Ask a cross-module question and get an answer grounded in resolved, related, current data — not raw rows the model had to decode.
- Trust the answer enough to act on it, because the same record always produces the same context.
- Know that what the AI can see is defined in one place per entity, not scattered across integrations.
The serializer will never be the headline feature. It's the layer that decides whether the headline features are true.
If you'd like to be among the first to use Cyril, join the waitlist.