Arca Ring docs
How Arca works.
Arca is a ring and an agent that remember the people you meet in real life. A tap swaps who you are. A conversation becomes something your agent can recall. Over time, every meeting adds to a map of your relationships.
Three parts are live today: the App Clip that opens when your ring taps an iPhone, the web card for Android and any browser, and the exchange relay that carries one person's details to the other. The ring itself is NFC with an LED light channel; the ring mic and haptics are concepts. The typed relationship graph and the agent API described below are a preview.
How a tap works
- Tap. The ring holds an NFC record with your card address,
ring.heyarca.app/c/<handle>. No battery is needed for the tap. - Card. On iPhone the address opens the Arca Connect App Clip with your card. On Android, or anywhere else, the same address opens the web card.
- Agree & Connect. The other person can continue with Apple to fill in their name and email, or type it. Nothing is sent until they tap Agree & Connect.
- Exchange. Their details go to the relay with the time, how you met and, if they allow it, a recording consent flag.
- Pickup. Your app pulls the exchange, saves it on your iPhone and deletes it from the relay. Anything not picked up within 30 days is deleted.
Data & privacy
- Your people, encounters and conversation summaries are stored on your iPhone.
- The relay keeps an exchange only until your app picks it up. It keeps no IP addresses with the details; a salted hash of the network address lives about two minutes to slow down abuse.
- Conversations are recorded only after consent. Audio and transcripts are not kept on our server.
- No ads, no analytics and no tracking cookies on the web card.
The full policy: ring.heyarca.app/privacy.
Ontology schema Preview
Arca's memory is a typed graph. It starts empty. Types and relations appear when something real needs them: the first tap creates a Person and an Encounter, the first conversation adds Topics and Promises. Nothing is designed up front.
Entities
| Type | What it is | Key fields |
|---|---|---|
| Person | Someone you met | name, handles, org, role |
| Encounter | One meeting: who, when, where, how | at, place, via (ring, card, qr, link) |
| Place | Where an encounter happened | name, area |
| Topic | Something you talked about | label |
| Promise | Something someone said they'd do | what, owner, due, status |
| Organization | Where a person works | name |
| Circle | A group that formed on its own, like people from one event | name, reason |
Relations
| Relation | From → to |
|---|---|
| connected | You → Person |
| met_at | Person → Encounter |
| located_at | Encounter → Place |
| talked_about | Person → Topic |
| promised | Person → Promise |
| works_at | Person → Organization |
| introduced_by | Person → Person |
| interested_in | Person → Topic |
| member_of | Person → Circle |
Provenance
Every fact records where it came from: tap (the exchange itself), conversation (with the speaker and the line it came from), manual (you typed it) or inferred (derived from other facts). You can always ask "why does Arca think this?" and get the source.
Confidence
Facts carry a confidence from 0 to 1. Taps and your own edits are 1. Facts from conversations depend on the transcript and who said them. Inferred facts, like "Sora and Daniel should meet", stay suggestions until you accept them.
How the schema grows
New entity types and relations are proposed when the same kind of thing keeps showing up in your encounters. A proposal becomes part of your schema when it's been seen enough times and fits the existing types; every change is versioned, so agents can read which version they're looking at.
Agent API Preview · not shipped
The plan: the same graph, served to Claude, ChatGPT or your own agent over MCP and a small HTTP API, read-only by default and scoped to what you approve. These endpoints are planned and may change.
arca.people.get(name)
A person, their orgs, encounters and the latest summary.
arca.encounters.search(where, when)
Meetings by place and time range.
arca.conversations.summary(person)
What you talked about, with sources.
arca.promises.open()
Promises still open, yours and theirs.
arca.circles.list(event)
Groups that formed around an event.
arca.context.for(person)
The brief your agent reads before a meeting.
// Claude, through the Arca MCP server (preview)
await mcp.call("arca.context.for", { person: "Sora Lee" })
{
"person": { "name": "Sora Lee", "org": "Voyager", "role": "Partner" },
"met": [{ "event": "YC dinner", "when": "2026-10-12", "where": "SoMa, SF", "via": "ring" }],
"talked_about": ["agent memory", "demo day"],
"open_promises": [{ "what": "Send the deck", "due": "before Oct 14", "age_days": 3 }],
"mutuals": ["Daniel"],
"brief": "Bring the deck. She offered an intro to Daniel; ask about it.",
"provenance": { "sources": ["tap", "conversation"], "confidence": 0.92 }
}
# The same call over HTTP (preview)
curl https://api.heyarca.app/v1/context?person=Sora%20Lee \
-H "Authorization: Bearer $ARCA_AGENT_TOKEN"
Exchange API Live
The relay behind the tap. Base URL https://arca-connect.arca-labs.workers.dev. Browsers may call the public endpoints only from https://ring.heyarca.app. Limits: 60 GET and 10 POST requests per minute per network address; over that you get 429 slow_down.
GET /profile/:handle
The public card an owner published. handle matches ^[a-z0-9][a-z0-9_-]{0,31}$.
200 { "handle": "min", "name": "Min Park", "role": "Founder", "company": "Arca Labs",
"bio": "Building how people and agents work together.",
"links": ["https://heyarca.app"], "avatar": 0,
"photoUrl": "https://arca-connect.arca-labs.workers.dev/photo/min?v=…" }
400 { "error": "bad_handle" } 404 { "error": "unknown_owner" }
photoUrl is present only when the owner added a photo (JPEG). avatar is 0–11: six colors by avatar % 6, round with a sprout below 6, rounded square with ears from 6.
GET /photo/:handle
The owner's photo as image/jpeg, or 404 no_photo.
POST /exchange
Sends a visitor's details to an owner. JSON body, about 120 KB at most.
| Field | Rule |
|---|---|
| consent | Required, must be true, else consent_required |
| ownerHandle | Required, a valid handle of an existing owner (bad_handle, unknown_owner) |
| name | Required, 1–40 characters (bad_name) |
Optional, a valid address up to 254 characters (bad_email) | |
| phone | Optional, digits, spaces, ( ) and -, 6–24 characters, may start with + (bad_phone) |
| links | Optional, up to 3 https:// URLs, 200 characters each (bad_links) |
| place | Optional, up to 80 characters (bad_place) |
| via | Optional, ring, card, qr or link; anything else becomes link |
| metAt | Optional, Unix seconds within two days of now; otherwise the server time |
| fromHandle | Optional, the sender's own handle when they have the app (bad_handle) |
| recordingConsent | Optional boolean, "Okay to remember this conversation" |
| photo | Optional base64 JPEG, about 80 KB (bad_photo) |
curl -X POST https://arca-connect.arca-labs.workers.dev/exchange \
-H "content-type: application/json" \
-d '{"ownerHandle":"min","name":"Sora Lee","email":"sora@example.com",
"via":"ring","place":"YC dinner","consent":true,"recordingConsent":true}'
201 { "id": "5b0c…" }
400 { "error": "bad_email" } 404 { "error": "unknown_owner" } 429 { "error": "inbox_full" | "slow_down" }
App-only endpoints
The Arca Connect app uses a bearer token for POST /owners, PUT /profile, PUT|DELETE /photo, GET /inbox, DELETE /inbox/:id and DELETE /owners/me. Picking up an exchange deletes it from the relay.