---
title: Present Manifests to your users
category: read
summary: Turn Manifests into a brief people enjoy reading. Write the narrative from the Brief, reason with the Signal, and link every item to its source.
order: 14
updated: 2026-10-07
next: charts-tables-and-infographics
related: signals-briefs-and-records, run-and-edit-a-beacon
reference: /agent-guide.md, /synorb-instructions.md, /agents/personal-agent-onboarding.txt
---

Your user judges Synorb by what you show them, not by the data you pulled. The same Manifests can reach a person as one dense block of text, a bare list of headlines, or a short update that respects their time. This guide shows how to produce the short update.

## When to use this

Use it for every delivery to a person: an on-demand answer, a daily Beacon check, a proactive ping, a first-run dry run. If a human will read it, lay it out.

Each part has one job:

- **The Brief** is the human narrative. Write the story from it.
- **The Signal** is for you. Use its Claims to verify, rank and compare, and to read exact numbers. Do not paste it.
- **The source link** is for your user. Every item gets one, so they can go to the original.

## Smallest working call

Every Manifest delivery already carries `presentation_items`, one entry per Manifest, shaped for display. Pull a few:

```mcp billed
synorb-manifests
{"stream_ids": ["STREAM_ID"], "days": 2, "target_count": 5}
```

Match each `presentation_items[]` entry to its Manifest by `manifest_id`. Then turn them into an update. This function is a complete, working starting point. It ranks by significance. It links each item with the label that Synorb supplies. It moves low-significance items to an "also seen" line:

```python
SIGNIFICANCE_RANK = {"high": 0, "medium": 1, "low": 2}
COMPANY = {"company_first_party", "corporate_blog"}
RESEARCH = {"academic_preprint", "peer_reviewed_journal"}


def group_of(item):
    # A starting heuristic only. `category` is the source's class, not a
    # news-versus-research label, so adjust this from the item's content.
    if item.get("category") in COMPANY:
        return "Company news"
    if item.get("category") in RESEARCH:
        return "Research"
    return "Other updates"


def link(item):
    action = item.get("action")
    if isinstance(action, dict) and action.get("url"):
        return f" [{action.get('label') or 'Read source'}]({action['url']})"
    return ""  # no valid URL: leave it unlinked, never invent one


def to_markdown(data, max_items=None):
    items = sorted(
        data.get("presentation_items") or [],
        key=lambda i: SIGNIFICANCE_RANK.get(i.get("significance"), 3),
    )
    limit = max_items or (data.get("render") or {}).get("max_items") or 5
    main = [i for i in items if i.get("significance") != "low"][:limit]
    rest = [i for i in items if i not in main]
    if not main:
        return "Nothing in this window is worth your time."
    lines = [f"**{main[0].get('one_liner') or main[0].get('title')}**", ""]
    n = 0
    for group in ("Company news", "Research", "Other updates"):
        members = [i for i in main if group_of(i) == group]
        if not members:
            continue
        lines.append(f"**{group}**")
        for item in members:
            n += 1
            why = item.get("why_it_matters") or ""
            lines.append(f"{n}. **{item.get('title')}**: {item.get('one_liner') or ''} {why}{link(item)}".strip())
        lines.append("")
    if rest:
        lines.append("Also seen: " + "; ".join(i.get("title") or "" for i in rest) + ".")
    return "\n".join(lines).strip()
```

## What you get back

The fields to render, per item. The values are illustrative.

```json response
{
  "data": {
    "presentation_items": [
      {
        "manifest_id": "...",
        "title": "Example AI announces Model A",
        "headline": "Example AI announces Model A",
        "one_liner": "Model A is now available for production workloads.",
        "full": "...",
        "why_it_matters": "This changes the capabilities available for the workflow you follow.",
        "significance": "high",
        "date": "2026-10-06",
        "category": "company_first_party",
        "source_label": "Example AI newsroom",
        "source_url": "https://example.com/model-a",
        "action": {"label": "Read source", "kind": "read", "url": "https://example.com/model-a"}
      }
    ],
    "render": {"suggested_format": "digest", "max_items": 3, "headline": "Company news and research"}
  }
}
```

`headline`, `one_liner` and `full` are the same item at three lengths. Pick one per display: `headline` for a notification or list row, `one_liner` for a chat line, `full` for a card or long-form view. `render.suggested_format` (`digest`, `single_highlight` or `list`), `max_items` and `also_suitable` are hints for your display. You can override them.

Take the sample delivery in the [personal agent onboarding file](/agents/personal-agent-onboarding.txt). It has three items: one company announcement, one research item and one low-significance notice. For this delivery, `to_markdown` produces the following text. Your user sees this text:

```markdown
**Model A is now available for production workloads.**

**Company news**
1. **Example AI announces Model A**: Model A is now available for production workloads. This changes the capabilities available for the workflow you follow. [Read source](https://example.com/model-a)

**Research**
2. **Independent Model A evaluation**: A research group compared Model A with prior systems. This gives independent context for evaluating the release. [Read source](https://example.com/evaluation)

Also seen: Example AI status notice.
```

### The shape of a good delivery

1. **A lead line.** One sentence with the thing your user most needs to know, and why it matters to them. Do not rephrase the `summary` field.
2. **Three to five items**, each with a title, a why-it-matters line for this user, and its source link. Three Streams covering one event is one item with three sources, not three items.
3. **An "also seen" line** for anything that did not make the cut, or nothing at all.
4. **One follow-up offer** tied to the lead: "Want the full argument from the memo?" Ask one question. Do not offer a menu.
5. After a Beacon run, ask whether the mix was useful and offer to adjust the same Beacon.

### Match the shape to the question

| Your user asked | Show |
| --- | --- |
| "Catch me up" / "what changed" | A timeline, in date order |
| "Compare X and Y" | A small table, one row per entity, columns from each Brief's `facts` (`brief.facts` in compact output, `brief.body.facts` in full output) |
| "Track this number" | A chart or stat card from `facts` (see the next guide) |
| "Anything urgent?" | Only `significance: high` items, or one line saying nothing is |
| A specific question | The direct answer first, then the items that support it |
| A report or newsletter | Sectioned prose grouped by theme or source, with inline links |
| No screen (voice) | A spoken briefing of the same selected items, with no URLs read aloud |

Never build a shape the fields cannot back. A table needs comparable `facts`, and a chart needs real numbers. The server builds `render.also_suitable` from compact Brief facts, so it can be empty on full-body and REST pulls. Check the facts yourself.

### When the Brief is thin

If `source.content_quality` is `thin`, the Brief does not give a full story. Choose your top two or three items for this user, read their Record (on plans that include it) or open the cited source, and write from that. Put the rest in the "also seen" line. Do not pad a thin window.

## Failure modes

| Symptom | Cause | What to do |
| --- | --- | --- |
| One dense block of prose | The delivery was written as one paragraph | Use the lead line plus items structure above. |
| A bare list of headlines | No why-it-matters and no links | Add a reason per item, specific to this user. |
| A link points to the wrong item | Items were matched by position | Match on `manifest_id`. |
| `action` is `null` or `source_url` is empty | No valid item URL exists | Show the item unlinked. Never invent a URL or link the source channel homepage. |
| A podcast shows only a landing page | `link_type` describes the link, not the media | Read `media_format` to tell audio from text. The `action.label` says "Listen now" or "Watch now" when it applies. |
| Low-significance research crowds out company news | You ranked by arrival order | Sort on `significance` and group by subject. |
| An ID looks off by a few digits | A 17-digit ID passed through a JavaScript number | Keep every ID a string end to end. |

## Make it good for your user

Write like a sharp colleague, not a list of headlines. Say what changed, why it matters to them in particular, and where to read more. Keep your own caveats out of the item. If needed, put them in one honest line: "mostly company announcements today; the research was thin".

If nothing is worth their time, say so in one line. This builds more trust than padding does.

## Next guide

[Charts, tables and infographics](/agent-resources/charts-tables-and-infographics): when the numbers deserve a picture, and how to draw one honestly.
