The Trust Boundary Is a Data Type: A Worked DAL Challenge
A hybrid agent can research broadly while keeping consequential actions narrow—but only if the workflow carries authority as data instead of leaving it to prose.
This article works through a small DAL challenge: design a travel workflow that may use decentralized evidence sources and a centralized booking service without confusing research confidence with permission to commit.
The challenge: one request, two kinds of authority
Suppose a traveler asks: “Find a reasonable trip, compare the options, and book the best one.” The request combines reversible research with an external purchase. A useful implementation must answer two separate questions:
- 1. What facts support the recommendation?
- 2. Which exact action is the agent authorized to perform?
A hybrid architecture makes the distinction more important, not less. Sources may be decentralized—provider feeds, public schedules, local information, or user-supplied documents—while booking may pass through one centralized API. Those systems have different reliability, identity, and failure properties.
Start with a small decision record rather than an itinerary paragraph:
```dal let trip = { origin: "SFO", destination: "YVR", dates: { start: "2026-09-10", end: "2026-09-13" }, travelers: 2, budget: { amount: 900, currency: "USD" } }
let decision = { trip: trip, stage: "research", authority: "prepare_only", status: "open" } ```
The important field is not the destination. It is authority. By making it explicit, downstream steps can refuse to turn a recommendation into a booking merely because the model’s wording sounds decisive.
Model evidence separately from trust in the action
The next step is to collect candidate options with evidence attached. A source can be useful without being sufficient for a purchase. For example, a public schedule may establish that a route exists, while only the booking provider can establish current inventory and checkout terms.
``dal let candidate = { kind: "flight", route: "SFO-YVR", observed: { departure: "2026-09-10T09:20:00-07:00", arrival: "2026-09-10T11:45:00-07:00", total: { amount: 410, currency: "USD" } }, evidence: [ { source: "schedule-feed", observed_at: "2026-08-23T14:00:00Z", claims: ["route", "scheduled_times"] } ], verification: "needs_provider_recheck" } ``
This record makes a useful claim and a limited claim. The route and scheduled times were observed. The price is an observation, not a guarantee. needs_provider_recheck prevents an old research result from masquerading as a current offer.
In a decentralized setting, evidence may arrive from several independent sources. Preserve provenance and timestamps instead of collapsing everything into one confidence score. A single number can hide the difference between corroborated facts, stale facts, and assumptions supplied by the traveler.
Use a contract for the transition to booking
After comparison, the agent can prepare a booking proposal. It should not mutate the original decision into “approved”; it should create a narrower contract describing the proposed effect.
```dal let proposal = { action: "book_flight", provider: "booking-service", candidate_id: candidate.route, total: { amount: 410, currency: "USD" }, cancellation_terms: "recheck_at_checkout", authority: "requires_approval", idempotency_key: "trip-sfo-yvr-2026-09-10-flight-01" }
if decision.authority == "prepare_only" { return { status: "awaiting_review", proposal: proposal } } ```
The proposal is deliberately complete enough to review: provider, action, amount, terms, and retry identity. It does not claim that a booking exists. The distinction between proposal and booking is a data boundary that can be tested.
If approval arrives, bind it to the proposal—not merely to the traveler’s original sentence:
```dal let approval = { proposal_key: proposal.idempotency_key, approved_total: proposal.total, approved_action: proposal.action, approved_at: "2026-08-23T14:12:00Z" }
let can_commit = approval.proposal_key == proposal.idempotency_key && approval.approved_total == proposal.total && approval.approved_action == proposal.action ```
If the provider changes the price, can_commit must become false. The agent should return a new proposal for review rather than silently spending more. This is where a hybrid design earns its keep: source diversity can improve discovery, but the centralized commit boundary still needs exact authorization.
Treat provider responses as state transitions
The booking call should produce a receipt whose status matches what the provider actually established. A timeout is not the same as a rejection, and acceptance is not necessarily final confirmation.
``dal let receipt = { action: proposal.action, idempotency_key: proposal.idempotency_key, status: "unknown", provider_request_id: null, observed_at: now() } ``
Possible transitions are intentionally small:
requested— the commit was sent;confirmed— the provider returned a confirmation;rejected— no booking was accepted;unknown— the outcome cannot yet be established;needs_reapproval— the proposed effect changed;needs_reconciliation— the request may have committed but requires lookup.
For unknown, do not issue a second booking just because the first response timed out. Query the provider with the idempotency key or request identifier. For needs_reconciliation, surface one bounded next step to the operator. A calm system is not one that hides ambiguity; it is one that gives ambiguity a controlled route to resolution.
Test the boundary, not just the itinerary
A small acceptance suite can prove more than a long demonstration. Test that research can complete without approval, while commit attempts fail closed when approval is absent or mismatched.
``dal assert(research(decision).status == "open") assert(commit(proposal, null).status == "approval_required") assert(commit(proposal, approval).action == "book_flight") assert(commit(changed_price_proposal, approval).status == "needs_reapproval") assert(retry(receipt).uses_same_idempotency_key == true) ``
Also test evidence failure: a source disappears, timestamps are stale, or two sources disagree. The correct response is not to invent consensus. Mark the affected field unresolved and keep the proposal from crossing the commit boundary until the relevant fact is checked.
This is a practical interpretation of @trust: trust is not a mood attached to the whole agent. It is a contract on a particular claim, transition, or external effect. Some attributes can be verified locally; others require a provider response or human approval.
Next steps for builders
Implement one narrow workflow with four explicit records: request, evidence-bearing candidate, approval-bound proposal, and outcome receipt. Keep decentralized discovery useful but modest in its claims. Keep centralized booking authoritative only for the facts that service can establish, and never let either source grant permission implicitly.
Then inspect the operator surface. It should answer, in one view: what was found, what was verified, what would happen on approval, and what remains unresolved. If those answers require reading model prose, the data contract is too weak.
The goal is not to choose hybrid or decentralized architecture as a slogan. It is to give each part of the system the smallest authority it needs. When trust and permission are represented as data, an agent can explore widely, pause cleanly, and commit only when the evidence and approval line up.