# what an agent hands back (AgentDeliverable)

> 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.

<!-- id: agent-deliverables · area: agent · stability: stable · html: https://osysharp.com/reference/agent/deliverables/ -->

## Summary        {#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 Osysharp.Agents;`, alongside [the agent task log (AgentTask)](https://osysharp.com/reference/agent/task-log/).

## Signature      {#signature}

```osy syntax
using Osysharp.Agents;

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

The fields you will read:

| field | what it holds |
|---|---|
| `Task` | the work this is an outcome of |
| `Kind` | `Document`, `File` or `Record` — which of the three below carries the content |
| `Sequence` | the agent's own ordering, from 0 |
| `Label` | what this IS, in a few words — the line a reviewer scans, and what groups related rows |
| `Document` | `Kind = Document`: the markdown the agent wrote |
| `FileAsset` | `Kind = File`: the file it produced |
| `EntityTypeName` · `EntityId` | `Kind = Record`: the record it created |

And from the other side, on the task itself:

| field | what it holds |
|---|---|
| `AgentTask.Deliverables` | every outcome of that task, as a collection |

## Description    {#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 Osysharp.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       {#examples}

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

```osy title="agent-deliverables-read-rule" test app=agent-deliverables
using Osysharp.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       {#see-also}
- [the agent task log (AgentTask)](https://osysharp.com/reference/agent/task-log/) — the work itself: what caused it, when it ran, what it cost.
- [agent conversation memory (using Osysharp.Agents)](https://osysharp.com/reference/agent/conversation-memory/) — what the agent SAID, as against what it handed over.
- [running an agent from your code](https://osysharp.com/reference/agent/ask/) — running an agent from your own code.
