Core concepts / Verification
Verification
Before Shadway calls a job done, it confirms what actually happened out in the world. It doesn't take the agent's word for it, and it doesn't trust a "success" response from an API. It checks the real result.
A 200 OK from an email API isn't proof the email arrived. A supplier saying "it
shipped" isn't a tracking record showing it did. Shadway keeps the claim and the
proof apart, and a mandate is done only when the proof backs up the claim.
Facts
A fact is something Shadway knows about the job, like the price of an order or whether it was delivered. Shadway writes facts as the work happens. There is no way to write a fact through the API, so no one can edit the record to make a job look finished.
amount_minor790000verifieddelivery_date"2026-09-11"verifieddeliveredtrueassertedamount_minor ≤ 799999Backed by a verified fact, within boundsdelivered = trueThe fact is only asserted. The supplier said so, and nothing confirmed itEach fact has a status that says how sure Shadway is:
verifiedandderived: confirmed.observedandasserted: seen or reported, but not confirmed.stale,conflicted, andcontradicted: out of date, or in conflict with something else Shadway knows.unknown: a gap Shadway is tracking.
Every fact also records where it came from: an action the agent took, an event, a piece of evidence, or a check. No fact appears without a source.
for await (const fact of shadway.mandate(mandateId).facts.list()) {
console.log(fact.key, fact.value, fact.status);
}for fact, err := range client.Mandate(mandateID).Facts(ctx, nil) {
if err != nil {
log.Fatal(err)
}
fmt.Println(fact.Key, fact.Value, fact.Status)
}Evidence
Evidence is the actual source behind a fact: a line in an email, a field in an API response, a page of a document. It's the real quote, not a summary. Each piece records where it is, a short excerpt, and how strong it is: who produced it, whether Shadway confirmed where it came from, and whether it's firsthand.
Shadway doesn't rank sources on a fixed scale. It weighs each one against the specific claim. A contract term is settled only by a signed agreement, and an account balance only by an account record. A supplier's email saying a package shipped proves the supplier said so, not that it shipped.
for await (const evidence of shadway.mandate(mandateId).evidence.list()) {
console.log(evidence.title, evidence.quality.sourceClass, evidence.excerpt);
}for evidence, err := range client.Mandate(mandateID).Evidence(ctx, nil) {
if err != nil {
log.Fatal(err)
}
fmt.Println(evidence.Title, evidence.Quality.SourceClass, evidence.Excerpt)
}Evidence points to artifacts: the documents, emails, and records the mandate fetched or received, saved exactly as they arrived. Downloads use short-lived signed links, and the record never stores a link with credentials in it.
Issues, assertions, and information needs
Longer jobs also track their open questions. An issue is a question the work needs to answer, like "Will the supplier honor the quoted price?" An assertion is a claim someone made about it. An information need is something the agent still has to find out. Issue states only move forward: a reply that acknowledges a question without answering it doesn't count as answered. Shadway tracks who said something separately from how well it holds up. These are read-only. Use them to see what the agent is still working out, not just what it has concluded.
Success criteria and completion
Success criteria are the conditions you set for "done": for example, the order
cost under $8,000 and was delivered. When the agent says the job is done, Shadway
doesn't take its word. It checks each criterion against confirmed facts, and marks
the mandate completed only if they all hold.
So a mandate that has to confirm delivery can't finish on the agent's say-so. It has to actually confirm it, through an integration whose results Shadway trusts, or by reading it back from a system of record.
When an outcome is unclear
Sometimes a failure is really an unknown. The request to place an order times out, but the order might have gone through anyway. If the integration can check, Shadway checks: it looks up what actually happened and records both the timed-out attempt and the answer.
If that check also fails, the outcome stays unknown. Shadway does not mark it a failure, and it never assumes it's safe to try the action again. See Execution for how this works with retries.