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

RingAn NFC tag carries your card link
Their iPhoneThe link opens the App Clip
Arca relayHolds the exchange until pickup
Your phoneThe card lands, deleted from the relay
  1. Tap. The ring holds an NFC record with your card address, ring.heyarca.app/c/<handle>. No battery is needed for the tap.
  2. 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.
  3. 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.
  4. Exchange. Their details go to the relay with the time, how you met and, if they allow it, a recording consent flag.
  5. 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

TypeWhat it isKey fields
PersonSomeone you metname, handles, org, role
EncounterOne meeting: who, when, where, howat, place, via (ring, card, qr, link)
PlaceWhere an encounter happenedname, area
TopicSomething you talked aboutlabel
PromiseSomething someone said they'd dowhat, owner, due, status
OrganizationWhere a person worksname
CircleA group that formed on its own, like people from one eventname, reason

Relations

RelationFrom → to
connectedYou → Person
met_atPerson → Encounter
located_atEncounter → Place
talked_aboutPerson → Topic
promisedPerson → Promise
works_atPerson → Organization
introduced_byPerson → Person
interested_inPerson → Topic
member_ofPerson → 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.

FieldRule
consentRequired, must be true, else consent_required
ownerHandleRequired, a valid handle of an existing owner (bad_handle, unknown_owner)
nameRequired, 1–40 characters (bad_name)
emailOptional, a valid address up to 254 characters (bad_email)
phoneOptional, digits, spaces, ( ) and -, 6–24 characters, may start with + (bad_phone)
linksOptional, up to 3 https:// URLs, 200 characters each (bad_links)
placeOptional, up to 80 characters (bad_place)
viaOptional, ring, card, qr or link; anything else becomes link
metAtOptional, Unix seconds within two days of now; otherwise the server time
fromHandleOptional, the sender's own handle when they have the app (bad_handle)
recordingConsentOptional boolean, "Okay to remember this conversation"
photoOptional 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.