# Revel Gifts: an end-to-end walkthrough

One worked example, from two people connecting their assistants to a gift suggestion. It
shows who does what: the assistants do the work, and each person only approves.

Everything here is synthetic: the people, handles, ids, dates and lease numbers. Tool inputs
match the live tools; where Revel returns wording you must quote, the example says so instead
of inventing it. For the full rules behind each step, read the guidance named at the end of
each part, at `https://api.revel.gifts/guidance/<name>.md`.

To keep the example short it shows facts only. An assistant can also write a short Gifting
Profile, a few sections that summarize the person and cite those facts; see
`revel-manage-profile`.

**The people.** Alex is getting into birdwatching. Sam is Alex's friend and wants to buy Alex
a birthday gift without asking what Alex wants.

## Where the person acts

| Step | Who acts | What the person does |
| --- | --- | --- |
| Connect an assistant to Revel | Person | Signs in on the hosted page, once per assistant |
| Look through context for gifting details | Assistant | Says yes to the assistant looking |
| Approve a contribution policy | Assistant proposes | Says yes to the exact changes Revel lists |
| Add facts to the profile | Assistant | Nothing; reads the summary afterwards |
| Pick a handle | Assistant | Chooses the handle |
| Ask to connect to someone | Assistant | Gives the other person's exact handle |
| Approve a connection request | Assistant proposes | Says yes to the exact changes Revel lists |
| Read a friend's shared profile | Assistant | Nothing |
| Ask a follow-up question | Assistant | Nothing |
| Answer a routed question | Assistant | Nothing, or answers one short neutral question |
| Suggest a gift | Assistant | Chooses the gift |

Tightening an audience, declining a request and revoking a connection never need a yes. The
assistant confirms the decision and says what it did.

## Part 1: Alex's assistant builds a profile

> **Alex:** Set me up on Revel Gifts.

The assistant confirms the account and reads what already exists.

```json whoami
{}
```

```json get_profile
{}
```

`get_profile` with no `handle` returns Alex's own `facts`, `summary` and `policy`. Here
`policy.policy` is null: Alex has not approved a contribution policy yet.

> **Alex's assistant:** You're connected to Revel as Alex. May I look through what I already
> know from our conversations for details that would help someone choose you a gift? I'll send
> only short summaries, never the conversations.
>
> **Alex:** Yes.

The assistant proposes the first policy. The first call leaves `owner_confirmed` out.

```json set_contribution_policy step=1
{"expected_version": null, "public_opt_in": false}
```

Revel refuses with `owner_confirmation_required` and a list of changes, one `- <change>` line
each. Nothing is written. The assistant quotes those lines word for word and shows the
proposed settings.

> **Alex's assistant:** Before I add anything, Revel needs your approval of a contribution
> policy. Revel lists these changes:
>
> *(each `- <change>` line, exactly as Revel returned it)*
>
> In short: interests, style, brands, wishes, dislikes, things you own, your birthday month and
> day and your city go to people you approve as Connections. Sizes, anniversaries and foods to
> avoid go to your Trusted Circle only. Nothing is Public. Do you approve?
>
> **Alex:** Yes, approve that.

Only now does the assistant repeat the identical call with the flag.

```json set_contribution_policy step=2
{"expected_version": null, "public_opt_in": false, "owner_confirmed": true}
```

Under the approved policy the assistant adds what it knows.

```json add_facts
{"facts": [
  {"category": "interest", "statement": "Is getting into birdwatching", "evidence_type": "explicit", "confidence": "high", "observed_at": "2026-10-01", "observed_precision": "month"},
  {"category": "style", "statement": "Prefers compact gear", "evidence_type": "explicit", "confidence": "high", "observed_at": "2026-10-01", "observed_precision": "month"}
]}
```

Each item comes back with its own `outcome`, `claim_id`, `status` and `audience`. Both are
`accepted` with status `active`.

Alex also needs a handle so friends can ask to connect.

> **Alex's assistant:** Which Revel handle would you like? Friends use it to find you.
>
> **Alex:** alex_demo

```json set_handle
{"handle": "alex_demo"}
```

> **Alex's assistant:** Done. I added two things to your Revel profile, visible to people you
> approve as Connections: you're getting into birdwatching, and you prefer compact gear. Your
> handle is alex_demo. You can change or remove anything by asking me or in Revel. Your other
> assistants may know different things about you; you can connect them too.

Guidance: `revel-get-started`, `revel-manage-profile`.

## Part 2: Sam's assistant asks to connect

Sam has already connected an assistant and set the handle `sam_rivers`, the same way.

> **Sam:** Alex's birthday is coming up. Alex is on Revel as alex_demo.

```json request_connection
{"handle": "alex_demo"}
```

Revel returns Alex's `display_name`, `handle` and `avatar_url`, and the pending request.

> **Sam's assistant:** I sent Alex a connection request. I can read what Alex shares once Alex
> approves it. I'll check when we next talk.

Guidance: `revel-connect-and-read`.

## Part 3: Alex approves the connection

Revel cannot wake an assistant. Alex's assistant sees the request the next time it looks.

```json list_connections
{"include": "requests"}
```

`incoming` holds Sam's request; its `id` is the `request_id`.

> **Alex's assistant:** Sam Rivers (@sam_rivers) asked to connect. Approving lets Sam's
> assistant read what you share; it doesn't let you read Sam's profile. Approve as a
> Connection, approve as Trusted Circle (sees more), or decline?
>
> **Alex:** A Connection is fine.

```json respond_to_connection_request step=1
{"request_id": "6f1d2b8e-3c4a-4e5f-9a7b-1c2d3e4f5a6b", "action": "approve", "tier": "connections"}
```

Revel refuses with `owner_confirmation_required` and the change list.

> **Alex's assistant:** Revel lists this change:
>
> - Let Sam Rivers (@sam_rivers) see facts you share with Connections
>
> Go ahead?
>
> **Alex:** Yes.

```json respond_to_connection_request step=2
{"request_id": "6f1d2b8e-3c4a-4e5f-9a7b-1c2d3e4f5a6b", "action": "approve", "tier": "connections", "owner_confirmed": true}
```

Sam is never told which tier Alex chose. Alex could also have done this on the Revel website.

Guidance: `revel-connect-and-read`.

## Part 4: Sam's assistant reads the profile and asks one question

> **Sam:** Any ideas for Alex's birthday? Around 80 dollars, and I want it to be a surprise.

```json list_connections
{"include": "requests"}
```

The request in `outgoing` is now `approved`.

```json get_profile
{"handle": "alex_demo"}
```

Sam's assistant sees the two facts Alex shares with Connections. It is weighing binoculars
against a field guide, and one gap would change the answer: does Alex already own binoculars?

The question carries only the fact needed. The occasion, date, budget and other ideas go in
`private_purpose`, which Revel uses to protect the plan and never shows to Alex or Alex's
assistants.

```json submit_question
{"handle": "alex_demo", "requested_information": "Does Alex already own binoculars?", "private_purpose": {"occasion": "birthday", "occasion_date": "2026-12-04", "budget": "80 USD", "candidate_ideas": ["binoculars", "birding field guide"], "notes": "Wants to keep it a surprise"}, "expires_in_hours": 48}
```

The result has a `question_id` and the `minimized_question` Revel will route.

> **Sam's assistant:** Alex shares that they're getting into birdwatching and prefer compact
> gear. I'm deciding between compact binoculars and a field guide, so I asked Revel whether
> Alex already owns binoculars. Alex won't see why I'm asking. I'll check for the answer when
> we next talk.

Guidance: `revel-find-a-gift`.

## Part 5: Alex's assistant answers

Alex's assistant checks for work at the start of a conversation, or from a recurring task its
host created with Alex's approval.

```json get_updates
{}
```

One `question_assignment` is waiting: the `minimized_question`, a verified `requester` (Sam),
an `assignment_id` and `lease_version` 1. It does not include the birthday, the budget or
Sam's other ideas.

The assistant reads Alex's profile and finds nothing about binoculars, so it will need to ask
Alex. It claims the assignment with `human_contact` true before saying anything.

```json update_assignment
{"assignment_id": "0b6e4c1a-9d2f-4a3b-8c7d-5e6f7a8b9c0d", "action": "claim", "human_contact": true, "lease_version": 1}
```

The claim succeeds with `lease_version` 2 and no `prior_user_contacts`. Only one assistant can
hold this lease, so Alex is never asked twice.

> **Alex's assistant:** Quick one: what gear do you usually bring on your birdwatching walks?
>
> **Alex:** The compact binoculars I bought last month.

The assistant reports that it asked.

```json update_assignment
{"assignment_id": "0b6e4c1a-9d2f-4a3b-8c7d-5e6f7a8b9c0d", "action": "report_user_contact", "lease_version": 2, "delivery_confirmed": true}
```

It records the new fact under Alex's policy, then answers and cites it.

```json add_facts
{"facts": [
  {"category": "owned_item", "statement": "Owns compact binoculars", "evidence_type": "explicit", "confidence": "high", "observed_at": "2026-11-12", "observed_precision": "day"}
]}
```

The item is `accepted` with `claim_id` `7c3e1f2a-4b5d-4e6f-8a9b-0c1d2e3f4a5b`.

```json submit_answer
{"assignment_id": "0b6e4c1a-9d2f-4a3b-8c7d-5e6f7a8b9c0d", "lease_version": 3, "body": "Yes, Alex already owns binoculars.", "evidence": [{"claim_id": "7c3e1f2a-4b5d-4e6f-8a9b-0c1d2e3f4a5b"}]}
```

> **Alex's assistant:** Thanks. I added "owns compact binoculars" to your Revel profile,
> visible to your Connections.

If the profile had already held that fact, the assistant would have answered from it without
asking Alex anything.

Guidance: `revel-answer-question`.

## Part 6: Sam's assistant suggests a gift

> **Sam:** Any news on Alex's gift?

```json get_question
{"question_id": "5d2a7b9e-1c3f-4e8a-9b6d-2f4c8e0a1b3d"}
```

The `status` is `answered` and the `result` is `answer`, with `answer.body` "Yes, Alex already
owns binoculars."

> **Sam's assistant:** Alex already has binoculars, so I'd drop that idea. Two suggestions:
>
> - A pocket birding field guide. It builds on Alex getting into birdwatching and fits the
>   preference for compact gear.
> - A lens cleaning kit, since Alex already owns binoculars.
>
> Both are under 80 dollars at the prices I just checked. Want me to compare a few field
> guides?

Revel does not pick the gift. Sam's assistant uses its own knowledge and tools, explains
which shared facts each idea relies on, and checks prices itself. Sam chooses.

Guidance: `revel-find-a-gift`.

## What stayed private

- Alex never learned that Sam was planning a birthday gift, the budget, or the other ideas.
- Sam saw only what Alex shares with Connections, and was never told the tier.
- Neither assistant uploaded a conversation. Revel holds short statements with their source
  type and date.
- Alex can narrow or remove any fact, or revoke Sam's access, at any time. It takes effect on
  Sam's assistant's next request.
