Ember

Request a 20‑minute call

We’ll reply within one working day to find a time.

Or write to hello@emberhub.dev. We only use this to reply to you.

Blog

Treat the facts an agent acts on as versioned dependencies

A reference design for agents that can tell when to proceed, when to ask a person and when to stop.

Agent tools have schemas, but the facts fed into them do not

We give agent tools structured schemas for customer IDs, dates, amounts and allowed operations. The fact that fills a field, though, usually arrives as a loose sentence with little history attached. An API can check that an amount is a number. It has no way to know that the number is the approved rate for this customer, this term and this date.

A safer design treats a business fact as a versioned dependency of the action that uses it. This is a proposed design pattern. It is not a claim that Ember currently ships the schema or APIs described below.

A fact needs an identity, a scope and its evidence

A fact record names the entity and the attribute, then states the conditions under which the value applies. For a renewal rate, those conditions might be the customer, currency, contract period and effective dates. Without a scope, two valid values for different situations can look like a contradiction.

The record should also keep source references, the times the sources were observed, the valid-time boundaries, the person or rule that resolved it, and a revision identifier. Keep the moment the system learned something separate from the moment it became true, since an agreement found today may have taken effect last month.

Store status as its own field next to the value. A fact can be supported, conflicted, missing, expired or superseded, and ‘unknown’ is a perfectly good answer. A free-form confidence score should never smooth over a conflict between two credible sources.

Resolve uncertainty with a state machine

Ingestion produces candidate claims, and a candidate is not yet a truth. Normalize entity IDs, currencies, units and time intervals before comparing them. Apply source-precedence rules only inside the scope they declare. When no rule settles the disagreement, assign an owner and ask a bounded question with the evidence attached.

A response becomes a new revision once the system has checked the responder’s authority and the answer’s scope. Silence never promotes a candidate to supported. If a deadline passes, the fact stays unresolved and the action that depends on it stays paused.

Human input has its own failure modes: people misread questions and answer outside their remit. So record exactly what they confirmed, let them correct it, and keep the competing evidence instead of overwriting history. LangGraph’s pause, persistence and resume mechanisms are one way to build the execution boundary, but they don’t supply these business rules for you. [3]

Check the dependencies again when the action happens

When an agent asks for a fact, it should say what it intends to use it for and when the decision is being made, instead of just asking for a string. A supported answer can carry the revision and its evidence references. A conflict should return the candidates and the reason execution is blocked, never a best-effort value dressed up as final.

When the agent prepares an action, bind it to the fact revision it used. Before committing, check that the required facts are still supported and that their revisions haven’t changed. This is optimistic concurrency: if the agreement changed after the action was prepared, revalidate it instead of sending it as it was.

When a source changes in a way that undermines the assumptions behind a resolution, mark the dependent resolutions for review. That takes business rules. A new email doesn’t always revoke an agreement, but a newly accepted amendment might. A time-to-live limits exposure, though it can’t tell you what actually changed.

Shared answers need their own access checks

A derived fact can reveal sensitive source material even when it quotes nothing, so reusing it across agents needs its own access decision. Treat evidence, resolved values and human answers as governed data, not as a cache that every tool may read.

Decide which audiences can see the value, which can inspect the evidence, and which can only learn that an unresolved dependency is blocking an action. Glean’s permission mirroring is a documented example of treating access as part of retrieval [4], and a resolution layer should keep that discipline instead of flattening it.

Measure the whole loop, including what the agent did

Test with contradictory records, delayed synchronization, conditional proposals, missing owners, ambiguous entities and a fact that changes between preparing an action and sending it. Measure conflicts missed, unnecessary escalations, resolution latency, questions per owner and how often answers are reused downstream. Then inspect the actions the agent actually took, not only whether the answer sounded right.

If you optimize only for completion, the agent learns to guess. If you optimize only for escalation, every task lands in a queue. The goal sits between the two: finish the work when its dependencies are supported, and make the remaining uncertainty cheap for the right person to resolve.

This is why the data plane matters. More capable agents can carry a wrong fact further, so a dependable one needs a fact layer that keeps evidence, authority, time and uncertainty attached to the value all the way to the moment the action counts.

Sources

[3] LangGraph: Interrupts (opens in a new tab)

[4] Glean: Core security principles (opens in a new tab)

Tell us your tools, and we’ll tell you what we’d connect first.Request a 20-minute call