All articles

Agent

The Agent in Your Day

18 min read

Every other article in this series is about how the agent works — how models are chosen, how the harness splits reasoning into layers, how tools are bound and skills shared. This one is about where all of that machinery actually touches you. Pixie is a relationship-care app; the agent exists for exactly one reason: to help you keep the people you care about close. Here is every surface where it does that, and how each one is wired underneath.

This is the last of the series' five top-level articles — the one where the machinery meets the product. If you have read Agent, you know the ground rules: the agent runs on your own device, its memory never leaves your control, and every model call goes through one routing seam. This article assumes those rules and shows the product built on top of them. When a surface leans on a mechanism covered elsewhere, we link down to it — the deepest dive from here is Mechanism: Memory & the Notebook, which underlies almost everything on this page.


1. One goal, six surfaces

A useful way to read this article: the agent shows up in your day in six places, and every one of them is a different answer to the same question — how does software help a human being stay close to other human beings without inserting itself between them?

you alone          you + one friend        you + your circle
─────────────      ─────────────────       ─────────────────────
agent chat         @pixie inline summon    huddles (agent ↔ agent)
the Notebook       proactive nudges        plans & scheduling

The left column is private cognition: a chat with your agent, and the Notebook where it keeps what it has learned. The middle column is the agent inside your conversations — but visible only to you. The right column is the one place agents talk to each other, and the human-facing plans that fall out of it.

One invariant spans all six, and it is worth stating before any mechanics: the agent reads and plans; it never sends, posts, or mutates your social world on its own. Its tool catalog is retrieval and planning only. When the right next step is a message to a friend, the agent drafts; you send. Keeping people close is your job — the agent's job is to make sure you never drop the thread without noticing.


2. The chat: a plain conversation with your agent

The simplest surface is a chat thread with the agent itself. It looks like any other conversation in the app, but the "peer" is your own agent, running locally.

Under the hood this is the harness at its most direct. The chat loop (ChatViewModel) asks LLMRouter — the single seam that decides which model serves a request, covered in Choosing Brains: the Model Bench — for a provider, and hands it the tool catalog. That catalog (AgentToolCatalog.all) is small, and every entry is read-only:

grep_memory        search the raw, append-only event log
read_event         read one memory event by id
read_conversation  read a message thread
read_post_thread   read a post + its comments
read_call          read a call transcript
search_file_index  find a file across your devices
check_notebook     search the agent's distilled memory (clear zone only)
list_devices       your own signed-in devices
current_date       resolve "today" / "this weekend" / …

Notice the shape: the agent's knowledge of your life is not stuffed into its prompt. It is fetched, on demand, through tools — the model asks check_notebook("Ada") when you mention Ada, instead of carrying every note about everyone into every conversation. Why retrieval beats context-stuffing — for privacy, for cost, and for small on-device models with small context windows — is the core argument of Mechanism: Memory & the Notebook. And when a request is complex enough to need multi-step work, the chat hands off to the layered runtime described in The L1–L2–L3 Harness, where a planner follows a skill and dispatches each real tool call through the single meta-tool of Mechanism: CallTool — One Tool to Bind Them.

The goal-tie is quiet here but real: the chat is where you ask "when did I last talk to Sam?", "what did Priya say about her interview?", "help me write something kind for Jordan's bad week." A model with no memory of your relationships can answer none of these. A model with tools over your own message history, on your own device, can answer all of them without a byte leaving your hands.


3. @pixie: summoning your agent into a conversation

The chat surface has one limitation: it lives in its own thread, away from the conversation you are actually having. Summon — the @pixie tag — fixes that. Inside any conversation — a 1:1 or a group — you type into the ordinary composer:

@pixie what did we decide about Saturday?

and your agent answers right there, inline in the thread. The prompt and the reply render as agent bubbles between the real messages. A bare @pixie with no text defaults to the most useful thing it could do in place: summarize this conversation and suggest a reply.

The critical property — the one the whole feature stands on — is that the other person never knows. The summon and the reply are summoner-only. Nothing is sent. Your friend does not see "…is asking their agent about you"; there is no typing indicator, no wire traffic to them at all. Concretely, AgentTag.isSummon recognizes a composer body that starts with @pixie (a mid-sentence mention like "ask @pixie later" is just text), and the exchange is persisted as local message rows flagged isAgentTag: true — rows that render in the thread but are never enqueued for delivery.

An invariant this important gets enforced structurally, not by convention. The send path has one chokepoint — ComposeService — and it refuses summon-prefixed bodies outright (assertPeerSendable), so even a future UI surface that forgets to intercept @pixie cannot accidentally leak a summon to a peer. If you have read the Contact Discovery series you will recognize the house style: when a property is load-bearing, put it at one chokepoint and make violating it a code-shaped impossibility, not a policy.

Two more wiring details are worth seeing:

  • Context is the thread, but as subject matter. The runner (AgentTagRunner) renders the last stretch of the conversation into a single block — "conversation so far (for context — do not reply to it directly)" — rather than replaying the peer's messages as chat turns. Your friend's words are the topic, not a speaker in the agent's dialogue. The agent then runs with the same routed provider and the same read-only tool catalog as the main chat, with a bounded tool loop.
  • Your other devices see it; your friend still doesn't. The exchange reaches your own iPad or Mac not by being sent but by the multi-device sync layer: your devices reconcile their local stores by comparing per-namespace Merkle digests and exchanging sealed sync_delta envelopes with each other. Agent-tag rows ride the ordinary messages namespace of that reconcile. Same-account sync and peer messaging are entirely different paths, which is exactly why one can carry the summon and the other structurally cannot.

Why does this serve the goal? Because the moment you most need your agent is mid-conversation — "what's their daughter's name again?", "summarize the last week of this thread", "draft something warmer than what I just typed" — and the moment you would least accept it is if asking made the other person feel surveilled or graded. Summoner-only is what makes an in-conversation agent socially safe, not just cryptographically safe.


4. Nudges: the agent that notices you drifting

Everything so far is reactive — you ask, it answers. The first proactive surface is the nudge: when you and a friend are drifting apart, the agent says so, gently, before the silence calcifies.

The design question is where a nudge should appear. A generic "engagement" notification from an app is noise. Pixie's answer: the nudge lands inside the drifting friend's own conversation thread, as an agent bubble — the same summoner-only, never-sent row an @pixie reply uses — plus a local notification titled with the friend's name, which deep-links straight into that thread. The place you are nudged is the place you can act.

┌──────────────────────────────────────────────┐
│  Maya                                        │
│  ──────────────────────────────────────────  │
│  [three weeks of nothing]                    │
│  ╭┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮  │
│  ┆ It's been 3 weeks since you and Maya   ┆  │  ← agent bubble,
│  ┆ talked. Want help drafting a hello?    ┆  │    only you see it
│  ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╯  │
└──────────────────────────────────────────────┘

The sweep (NudgeService.sweep) is deliberately conservative, and every guard exists to protect the relationship rather than the metric:

  • Drift is not a new signal. It reuses the Relationship Health engine's existing cadence read — RelationshipHealth.peer(...).lastContacted, computed over the same messages and calls the health dashboard shows you — thresholded at 21 days. One definition of "in touch" across the whole app; the nudge cannot disagree with the dashboard.
  • Only human contact counts. The drift read filters to human rows: agent bubbles and system notes are excluded. This closes a subtle self-defeating loop — a nudge that counted as contact would reset the very gap it flagged, and the agent would conclude the relationship was fine because it had been talking to you about it.
  • A relationship, not a directory entry. A contact with fewer than six lifetime messages never triggers a nudge. Someone you imported and never really talked to is not a friendship falling out of touch.
  • At most one nudge per contact per 14 days — and the cooldown stamp is derived from the nudge rows already in the thread, not from device-local settings. This matters on multiple devices: nudge rows sync between your devices like any other row, so a sibling device's nudge suppresses yours the moment it syncs in, and re-running the sweep is a no-op by construction. (The sweep itself is also gated to the current "driving" device — the driver's-seat role described in Agent — so two devices never sweep simultaneously.)
  • The body is generated, with a floor. The nudge text is a one-shot call through the same routed provider as everything else; on any failure it falls back to a static line ("It's been a while since you and Maya talked — 3 weeks. Want help drafting a hello?"). A nudge must never fail to have a body — and note the nudge rows even carry a distinct marker ("Pixie Nudge" vs. "Pixie") so a summoned reply in the thread never masquerades as a nudge, nor a nudge as a reply.

This is the feature that most directly is the goal. Drifting apart is rarely a decision; it is an accumulation of unnoticed weeks. A system that reads only your own local history, notices the gap, and offers to help you say hello — without telling the friend, without shaming you with a streak counter — is the smallest possible intervention that still changes the outcome.


5. Huddles: your agent meets your friends' agents

Everything above stays inside your own account. The huddle is the one place your agent represents you to others — specifically, to the agents of your closest people.

The idea is older than software: in a close-knit community, people quietly look out for each other — "did you hear Aarav's been having a rough time? You should check in." A huddle is that, mechanized with consent: at a global cadence tick, the agents of a mutually-trusting circle convene for a short, structured, encrypted conversation. Each agent brings a few gated notes about its own user, reacts to what the others share, and afterward tells its own user anything worth acting on. No human reads the live conversation — not the group, not even you.

A compressed tour of the machinery (each clause is a real mechanism, not a metaphor):

  • The cohort is a maximal clique of the mutual-consent graph. You mark someone inner-circle; if they mark you back, that edge exists. A huddle group is a set of people who are all pairwise mutual — computed server-side (the consent graph is the one thing the server holds) but disclosed minimally: you learn only the cliques containing you. The clique rule is decisive because a huddle shares sensitive inferred context: it guarantees nothing about you is ever spoken in front of an agent whose user you don't mutually trust.
  • Everything rides sealed envelopes + MLS. Turns are encrypted with MLS (Messaging Layer Security, RFC 9420 — the IETF standard for group end-to-end encryption, with cryptographic membership and healing after compromise) and sent through the relay as sealed-sender envelopes: the relay sees "an envelope for MLS group X," never which member sent it, never a word of content. Worth separating the two halves of what that buys, because they are not the same guarantee: MLS secures a group you are in, and says nothing about how you came to be in it. Admission is its own problem with its own answer — see Who Gets to Put You in a Group.
  • Inference is locked on-device. Huddle turns run only on an on-device model — the built-in system model or a local mlx-community model from the bench in Choosing Brains: the Model Bench — never a cloud provider, even if your personal agent is configured with one. Your read on your friends must not transit anyone's API. Each envelope also carries a hardware-backed App Attest assertion that the sender is the genuine, unmodified app, so "no one is logging this" is a wire-level check, not a promise.
  • The session is structured rounds, not a free-for-all. A greeting round, then one DISCUSS → NOTES round per brought note, over a queue that interleaves every member's notes fairly. A server-side mic rotation orders turns; everything meaningful rides inside the encrypted payload as flags on the turns themselves — a sticky move_on ("I'm done with this topic"), proposals, approvals. A round closes when every member has flagged done, with hard turn caps so a wedged device can never hold the cohort hostage. Silence is a first-class turn: an agent with nothing worth saying passes, and a pass can still carry an approval.
  • DraftGate is your binding control. Before the model ever sees context for a turn, DraftGate filters it: anything you flagged don't share in huddles is structurally invisible to the huddle reasoning — it never enters any prompt. You also steer with standing guidance in the Notebook ("be conservative about money," "celebrate my wins"). Pre-hoc steering plus a binding flag, instead of post-hoc transcript review — because there are no transcripts, for anyone, ever.

What you actually see afterward is deliberately small: a "Your Agent is huddling" Live Activity while it runs (no names, no details), and then the routed outcomes. A finished huddle's rounds pass through an outcome router that sends each item to its proper home: background learned about your friends is sealed into the agent-only zone of the Notebook (never rendered to you — see Mechanism: Memory & the Notebook for why you can't read it); follow-ups surface as your agent messaging you first — the one place it initiates a 1:1 chat ("sounds like Sophie could use a check-in about the job search"); and a fully-approved "we should get together" becomes a plan ask with Accept / Decline buttons. Everyone answers on their own device; when all answers are in (a 24-hour deadline counts silence as no), a deterministic member creates the Plan containing only the yeses.

The honest framing, straight from the design doc: the huddle is where you trust your agent's judgement without a receipt. You cannot audit what it said; you can only steer beforehand and flag things as unshareable. In exchange, your closest people get an early signal when you could use them — and you get the same about them. That conditional bridge — inference about you, reaching a friend's agent, surfacing as their gentle nudge to check in on you — is the entire point of the feature, and it is kept survivable by the clique rule, the on-device lock, and the encryption doing exactly what they say.


6. Plans: from "we should" to a time on everyone's calendar

Huddles discover; humans converge. The Plan is where a "we should get together" becomes a real time on real calendars — and it is also a standalone surface: any member of a group chat can spin up a Plan with a chosen subset ("start a plan for Ada's birthday dinner with these four").

A Plan is a separate, temporary thread with its own membership — not a group chat. It carries a scheduling poll, winds down when the event has happened, and can be promoted to a full group if a one-off dinner turns into an ongoing crew. Three mechanics do the work:

Scheduling is computed by everyone, revealed to no server. When a huddle spawns a plan, each agent merges its user's calendar into busy intervals and shares them as an encrypted turn; every device runs the same pure intersection over the same submissions and derives the identical common-free windows locally. The server never computes — or sees — the time. Those windows seed the poll.

Convergence is an in-thread poll with a unanimity lock. The poll card in the thread has two phases:

DISCUSS   candidate windows + live tallies — tap what works for you
LOCK IN   anyone proposes a concrete final time (free-form: "7–9 PM"
          inside the 6–9 PM window) → it locks only when EVERY
          participant accepts → each device writes the calendar event, once

Newest vote wins while discussing; the final time is unanimous or nothing. No server-side tally exists — votes, proposals, and accepts are just encrypted messages in the thread, folded into poll state by each device.

Membership is consent-shaped, down to the phone number. A Plan is an MLS group of exactly its members; you can decrypt its messages if and only if you are in it. Invites are accept-gated — an invitee sees a pending thread with Accept / Decline and is cryptographically added only on accept, so a decliner never holds keys. Any member can bring a friend, which makes disclosure rules matter: in the member list, names are always shown, but a phone number appears only if you're already connected to that person — bringing your friend into the dinner plan never exposes the other members' numbers to them, or theirs back. Even history is consent-shaped: an invitee sees prior messages only if the inviter chose to share them, and the default is off — a joiner starts from the present.

The goal-tie writes itself: the single most common failure mode of adult friendship is not conflict, it is the plan that never got made. Fourteen messages of "we should grab dinner!" and no dinner. A thread whose entire job is to converge — agents finding the window, humans picking within it, unanimity writing the calendar — is the agent harness aimed squarely at that failure.


7. The Notebook: what your agent remembers

Every surface above leans on the same substrate: the agent's memory. It has two levels. Below is the raw, append-only event log — every message, call transcript, and post, greppable by the grep_memory tool. Above it sits the Notebook: the distilled digest the agent actually reasons from — a page per person in your life, a "notes about you" page, short digests of past conversations and calls, and your standing behavioral guidance ("don't bring up health stuff in huddles"), which is the very section DraftGate enforces. A background distillation loop keeps it current: after a conversation or call accrues new material, the agent summarizes it into Notebook entries — incrementally and idempotently, always stamped with its source.

The Notebook's defining structure is its two zones:

  • The clear zone is yours: readable and editable under You → Agent → Notebook. Your edit is authoritative — the agent treats your version as ground truth. This is the alignment surface: you can literally read what your agent believes about your relationships and correct it.
  • The sealed zone is the agent's private workspace, encrypted under a key only the agent's runtime holds — you cannot read it, and no UI renders it. The hard floor: anything learned from other people's agents in a huddle is always sealed, with no path out. It is second-hand context shared in confidence; surfacing it would leak your friends' lives through your Notebook.

The boundary is enforced at the data layer (a sealed note can never be reclassified or rendered) and at the retrieval layer: the chat agent's only path into the Notebook is the check_notebook tool, which searches the clear zone exclusively. The user-facing agent literally has nothing sealed in reach — it cannot leak, or even confirm the existence of, a sealed note about someone, because it cannot distinguish "no note" from "a note exists but is hidden." Structural isolation instead of a system-prompt promise: the same chokepoint philosophy as @pixie's send-gate.

Why memory is grep-and-distill rather than context-stuffing, how tagging and retrieval work, and how the sealed zone's key is held — that is the deep dive: Mechanism: Memory & the Notebook. For this article the point is the role it plays: the Notebook is why the chat can answer "how's Priya doing," why a nudge can offer a draft that sounds like you, and why your agent walks into a huddle with something worth saying.


8. The pattern, once you see it

Lay the six surfaces side by side and one design pattern repeats:

Surface What crosses a boundary What never does
Agent chat tool reads over your own data your data, off-device without your say
@pixie summon nothing — summoner-only rows the summon, to your peer (send-gate refuses it)
Nudge a local notification, to you any signal to the drifting friend
Huddle DraftGate-filtered context, MLS-sealed, device-to-device transcripts (to anyone), flagged memories, cloud inference
Plan votes & times, encrypted to exactly the members phone numbers of unconnected members; history without the inviter's say
Notebook clear-zone notes, to you, editable the sealed zone — to anyone, including you

In every row, the social boundary and the technical boundary coincide, and the technical one is enforced at a chokepoint rather than by good intentions: one send-gate, one retrieval tool, one DraftGate, one unanimity rule. That is the whole philosophy of this series in miniature — the harness articles below this one (Choosing Brains: the Model Bench, The L1–L2–L3 Harness, Skills, Tools, and the @-Namespace, The Homebase) exist so that the surfaces on this page can make promises like "your friend never knows" and keep them structurally.

And the goal stays human-sized. Nothing here posts for you, replies for you, or performs friendship on your behalf. The agent remembers, notices, convenes, drafts, and schedules — and then hands you the phone. The last step is always yours, because the last step is the relationship.


References

Next: Mechanism: Memory & the Notebook — the substrate every surface above reads from.