Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Agent

what an agent hands back (AgentDeliverable)

partial entity AgentDeliverable { security { … } }

An agent presents its outcome as a LIST of deliverables, not a sentence: documents it wrote, files it produced, and records it created, in the order it chose. It records each one deliberately, by calling a tool for it, so the list is what the agent means to hand over rather than everything it happened to touch. The rows are written by the platform and can never be created, edited or deleted by app code; your app decides who may READ them, and builds the screens that show them.

stable1 example compiled by CIagenttaskoutcomecapability

Summary#

A task's Outcome is one sentence — enough for a list view, and never enough to act on. The deliverables are what the sentence is about.

Each thing an agent hands back is one AgentDeliverable row hanging off its task: a document it wrote, a file it produced, or a record it created. A task has as many as it needs, in the order the agent chose, and the three shapes sit in one list — so a screen can show a summary, the memo behind it and the twelve receipts that were filed, together.

AgentDeliverable arrives with using Osyrin.Agents;, alongside the agent task log (AgentTask).

Signature#

using Osyrin.Agents;

partial entity AgentDeliverable {
  security { allow read when IsAuthenticated; }
}

The fields you will read:

fieldwhat it holds
Taskthe work this is an outcome of
KindDocument, File or Record — which of the three below carries the content
Sequencethe agent's own ordering, from 0
Labelwhat this IS, in a few words — the line a reviewer scans, and what groups related rows
DocumentKind = Document: the markdown the agent wrote
FileAssetKind = File: the file it produced
EntityTypeName · EntityIdKind = Record: the record it created

And from the other side, on the task itself:

fieldwhat it holds
AgentTask.Deliverablesevery outcome of that task, as a collection

Description#

A list, because a sentence cannot carry an answer. "Checked the report and filed one receipt" tells a reviewer nothing they can open. The deliverables are the openable half: the policy check they can read, the memo they can download, the draft they can approve.

One row per thing, and grouping is yours. Twelve filed receipts are twelve rows sharing a Label, not one row that mentions twelve. A list can always be grouped for display; a group cannot be ungrouped, and the individual rows are what a reviewer clicks.

The agent records these DELIBERATELY, and that is what makes the list worth reading. The platform separately knows everything a task touched — that is the audit trail, and it is complete. This list is different: it holds only what the agent chose to present. Most rows an agent touches on the way to an answer are working material, and a list derived from them would bury the answer in bookkeeping.

So an agent that does the work and presents nothing leaves an empty list, and that is a finding worth showing rather than an error. It means the work happened and nobody can see what came of it. The platform will not refuse to finish such a task — an agent whose honest answer is "nothing to report" has to be able to say so.

A document is markdown, and that buys more than formatting. It is stored as a real document with sections, so it can be read section by section, edited afterwards, and — because it is indexed for recall — found later by what it SAYS. "What did we decide about the Lisbon policy" can find the deliverable that decided it, months on. A plain string would be a dead end in exactly the place it is most useful.

A deliverable never points at nothing. Recording a record or a file that does not exist is refused at the moment the agent tries, while the agent is still working and can fix it — rather than becoming a card on a review screen that looks live and opens nothing.

The rows are written by the platform. App code can never create, change or delete an AgentDeliverable: a fabricated one would claim an agent produced something it did not, and a deleted one would hide what it did produce. Attempting a write is refused.

Who may READ them is entirely yours, exactly as for the task log — a plain using Osyrin.Agents; gives you a table nobody can read yet, and you declare the rule you want. The review screen, the approval queue and the activity dashboard are your app's to build; these rows are the material.

Examples#

An app that lets any signed-in person read agent work and everything it produced:

using Osyrin.Agents;

[Principal] entity User {
  [Required, MaxLength(255)] string Email;
  security { allow read when IsAuthenticated; }
}

partial entity AgentTask {
  security { allow read when IsAuthenticated; }
}

partial entity AgentDeliverable {
  security { allow read when IsAuthenticated; }
}

With both rules in place, a task's outcomes are an ordinary collection on an ordinary entity: read task.Deliverables, order by Sequence, and render each row by its Kind.

See also#

Related

running an agent from your code

Call an agent you declared the way you would call anything else you declared — by name. You hand it the turns you want…

the agent task log (AgentTask)

Every piece of work an agent does is recorded as an `AgentTask` — which agent, what set it going, when it started and…

agent conversation memory (using Osyrin.Agents)

A conversation is stored as a `ChatSession` plus its `ChatMessage` turns, so an agent asked a follow-up can refer back…