Inspiration
Every AI agent meets you as a stranger. Spotify knows your music, Netflix knows your films, but the new assistant you just opened knows nothing, so it falls back on generic popularity. Two people with opposite tastes ask for "something to watch on Friday" and get the same list.
Personalization today means one of two bad deals: lock-in (each assistant keeps its own memory, as prompt text, in its own cloud) or surveillance (ad networks learned "know the user everywhere" by tracking people across apps, and Google is now retiring its Topics API as it shuts down Privacy Sandbox). Meanwhile, 71% of consumers expect personalization and 76% are frustrated without it (McKinsey), while 70% of Americans have little or no trust in companies to use AI responsibly (Pew).
MCP standardized how agents reach tools. Nothing standardizes how agents reach you. We built that layer: PCP, the Personal Context Protocol.
What it does
PCP is an open protocol that works with any agent:
- The user holds a passport (
pcp/0.1): public cultural entities they love, things they've rejected, and a small learned model. There's no PII; the ID is a random pseudonym. - Any agent (Claude, any OpenAI-compatible API, or a local Ollama model) sends its candidate options with its own probabilities.
- Qloo scores them.
qloo_rankscores every option against the user's taste across categories in one call, so an artist you love can shape your movie picks. - A distribution layer re-weights the agent's output. A per-user model blends the agent's prior with Qloo affinity into a new probability distribution.
- It trains on your device. Every 👍/👎 is one gradient step in the browser or CLI. No training data goes to any cloud.
- Minimal disclosure and encryption. Requests carry only public entity names plus two weights. Passports are exported with AES-256-GCM, so you can keep them anywhere (your own server, Google Drive, a USB stick) and the storage host only ever sees ciphertext.
- Three routes: an HTTP API (any language or framework), a CLI (terminals, scripts, local agents) and a JavaScript SDK (browser and Node).
How we built it
Qloo integration. All Qloo calls run on the server through the official qloo mcp server from @qloo/qloo-harness, so the key never reaches the browser. We use qloo_rank because PCP's job is exactly what that tool does: rank an agent's own shortlist against one taste profile. qloo_capabilities gives us a readiness check that doesn't use quota.
The distribution layer. For each candidate $i$ we build a feature vector from the agent's prior and Qloo's affinity, z-scored across the shortlist:
$$ \mathbf{x}i = \big[\,\log P{\text{agent}}(i),\; z(\text{affinity}_i)\,\big] $$
A conditional-logit model (a one-layer softmax network) with per-user weights $\mathbf{w}$ produces the new distribution:
$$ p_i = \frac{\exp(\mathbf{w}^\top \mathbf{x}_i)}{\sum_j \exp(\mathbf{w}^\top \mathbf{x}_j)} $$
On-device learning. When the user accepts ($+$) or rejects ($-$) option $c$, we take one gradient step on the log-likelihood:
$$ \mathbf{w} \leftarrow \mathbf{w} \pm \eta\,\big(\mathbf{x}c - \mathbb{E}{p}[\mathbf{x}]\big) $$
Likes become new taste signals and dislikes become vetoes. After a couple of interactions you can watch the weights move, for example from $[1.00, 1.00]$ to $[0.61, 2.36]$: this user trusts their taste graph more than the generic agent.
Privacy. disclose(passport) sends only what a request needs. The encryption is PBKDF2-SHA256 (310k iterations) feeding AES-256-GCM, via WebCrypto in the browser and Node. A single SDK file runs unchanged in both, so the CLI and the web app share the exact same model.
Stack: Node.js, the MCP SDK, the Qloo harness, vanilla JavaScript, WebCrypto, and Anthropic, OpenAI-compatible or Ollama models.
Challenges we ran into
- Personalizing without logits. Closed model APIs don't expose token logits, so we couldn't bias the LLM token by token. We moved the learned layer to the agent's output distribution over options. That works with any model, including ones we don't control.
- Usefulness vs. privacy. We wanted real taste intelligence without shipping a profile to a server. Minimal disclosure (public entity names only) plus on-device training was the balance we found.
- Stable learning from very little feedback. A few clicks shouldn't swing everything. We z-score Qloo affinity within each shortlist, clamp the weights and use a modest learning rate.
- Honest results. If Qloo can't score an option, the UI says so and shows the agent's raw distribution. We never fill the gap with guesses.
What we learned
- Personalization belongs in the agent's output distribution, not stuffed into prompt text.
- LLMs know what's popular; Qloo knows what goes together. That cross-domain affinity is exactly what an agent lacks.
- A tiny on-device model is enough to make personalization visible, portable and owned by the user.
What's next
- Personal Context Graph (v0.2): expand from taste to topics, moods and context (time of day, company), with a graph that local agents build and train on the device.
- Encrypted sync across devices, including a Chrome extension and self-hosted or Google Drive storage.
- Consent-based connectors that run on the device and add only public cultural entitie
Built With
- aes-256-gcm
- ai-agents
- anthropic
- claude
- cli
- conditional-logit
- css3
- html5
- javascript
- llm
- model-context-protocol
- node.js
- ollama
- on-device-learning
- openai-compatible-api
- pbkdf2
- personalization
- privacy
- qloo
- qloo-insights-api
- qloo-mcp
- rest-api
- softmax
- webcrypto
Log in or sign up for Devpost to join the conversation.