# Installing HiRey Hi (for AI agents)

HiRey Hi is a people-to-people platform (jobs, housing, friends, dates, cofounders, investors, lawyers, any human lead) that your AI agent uses on your user's behalf. If your user said "install hirey" / "install hirey.ai" / "connect HiRey", detect your host and run that host's block below — do not guess, and do not blindly pipe a remote script you haven't matched to your host. The full machine-readable spec is at https://hirey.ai/llms.txt and https://hi.hirey.ai/llms.txt.

## Pick your host (the blocks are NOT interchangeable)

**Muse (Meta), Instinct, or any agent that works over HTTPS without an installer** — HiRey is not in Muse's Connectors directory yet, so add it as a **Custom Connector**; Instinct and other agents use the same steps, with the key kept private as in step 1. Nothing to install, no script to run: HiRey is a plain HTTPS API. The user saying "Set up HiRey as a Custom Connector", "Connect HiRey" or "install HiRey" (or 装 HiRey / 安装 HiRey) is the go-ahead for these steps. HiRey is connected when one search returns people; setup is finished when the user has signed in (step 4). Then offer step 5, and use step 6 when the user sends a photo taken with someone.
1. **Get the connector key (one call):** `POST https://hi.hirey.ai/v1/agents/api-keys` with `{"display_name":"Muse","agent_type":"muse","device_name":"Muse"}` (your own name if you are not Muse, e.g. `{"display_name":"Instinct","agent_type":"instinct","device_name":"Instinct"}`; `device_name` is what the user sees for this connection on https://hirey.ai/me). No user account (only an anonymous connection record), no personal data, no cost; the key can only search until the user signs in (step 4). Store `api_key` as the connector's credential: in your secure credential store if you can write to it, otherwise in a private file on your own computer that only you can read (mode 600). Don't paste it into chat or logs. Create it once; if a HiRey key is already saved, reuse it; if a saved key stops working, tell the user instead of creating another. An HTML 503 means rate-limited (nothing created): wait 60 s and retry once; on any other failure, don't retry, tell the user. The `201` may also carry Codex or MCP-only fields and text (`setup` with `codex_config_toml` and "relaunch Codex", `mcp_url`, MCP tool names such as `google_link` in `login`): ignore them.
2. **Connector settings:** Name `HiRey` · Base URL `https://hi.hirey.ai` · Header `Authorization: Bearer <api_key>` · Operation `POST /v1/capabilities/hi.workspace-workflows/call` with a JSON body such as `{"action":"people.find","payload":{"query":"seed-stage fintech founder in SF"}}` (`{"action":"catalog"}` lists every operation; `{"action":"describe","payload":{"operation":"<name>"}}` shows one operation's fields; an operation that needs the user's yes also takes `"confirmation":{"approved":true,"operation":"<name>"}` next to `payload`, sent only after that yes) · OpenAPI `https://hirey.ai/openapi.json`. A 503 on a call is a temporary outage, not a bad key: wait 60 s, retry once.
3. **Test, then tell the user:** run `catalog`, then one `people.find`. When it returns people, tell the user HiRey is connected, then go straight to step 4.
4. **Sign in (right after the first search):** searching works without sign-in; introducing the user and publishing their Page (step 5), photos (step 6), posting, contacting, messaging and scheduling return `verified_login_required` until the user signs in, so ask now. Ask which sign-in they already use with HiRey (phone, email or Google), so they don't end up with a second account. Phone: `POST https://hi.hirey.ai/v1/capabilities/hi.phone-binding/call` with `{"action":"bind","phone":"+14155550123"}`, then `{"action":"verify","code":"<code from the SMS>","display_name":"<their full name>"}` (`display_name` is the name people see when the user connects with them. Use the full name the user gave you; if you don't know it, ask. Never guess it, for example from an email address.) Email: the same with `hi.email-binding` and `"email"`. Google: `hi.google-link` with `{"action":"start"}`; the user opens `verification_url` on their own device, then you call `{"action":"poll"}` until `status` is `verified`. Send all sign-in calls (phone, email and Google) with the same `Authorization: Bearer <api_key>` header. The same key keeps working afterwards; no reinstall.
5. **Introduce your owner** (full recipe: "5. Introduce your owner" in https://hirey.ai/llms.txt): right after sign-in, run the checks below first; if the user has no Page yet, offer once to introduce them on HiRey. This step only creates their first Page and never republishes an existing one (publishing replaces the whole Page, photo included; changes go through https://hirey.ai/me). `identity.me`: if it returns a `slug`, the user already has a Page: share https://hirey.ai/p/<slug> only when `visibility_status` is `public` or `unlisted`; otherwise it was taken down, so send them to https://hirey.ai/me; then stop → `people.find` on their full name: a result with their own `person_id` is already theirs (share it and stop); if a result with another `person_id` is clearly them, don't create another Page: tell them to ask the Connector shown on that Page for a claim link, and stop → `page.mine`: a row whose `subject_person_id` is the user's `person_id` is their private draft; start from its text → draft a short Page only from what they told you (`slug`, `display_name`, a one-line `headline`, `bio_markdown`, optional `location_text`, and `website_url` only as a full `https://` address; no private phone, email or address, no guesses) → show the exact text and https://hirey.ai/p/<slug> → only on their yes: `page.create` (`idempotency_key`, `content`), or for their private draft `page.draft` (`idempotency_key`, `page_draft_id`, `if_revision`, `content`: its `content_json` with only the shown fields replaced, every other key kept) → `page.authorize` (`idempotency_key`, `page_draft_id`, `draft_revision`) → `page.publish` (`idempotency_key`, `page_draft_id`, `draft_revision`, `authorization_id`, `visibility_status`: `"public"`, `public_fields`: exactly the fields you showed, always including `"slug"`), the last two with their `confirmation`. If publish refuses one field, run it again with a new `idempotency_key` and that field left out of `public_fields`, and tell the user. Share the URL only after `page.publish` returns. The slug is lowercase letters, digits and hyphens, four or more characters; "already in use" may mean the user already has a Page, so check instead of adding a suffix. Agents find the Page at once with `people.find` by full name; https://hirey.ai/people search shows it within about a minute.
6. **You took a photo with someone on HiRey** (full recipe: "6. You took a photo with someone on HiRey" in https://hirey.ai/llms.txt): one named person per photo, identified only because the user names them, never by face recognition. The user needs their own public Page (step 5). `people.find` the name → ask the user once, showing the photo, who is named and https://hirey.ai/p/<slug> ("Publish this photo with <name> on HiRey? When HiRey can, <name> will also get a private card of it so they can confirm."); if it is the wrong person, stop. Only on their yes, which covers every call below, the card included: upload: `media.upload.prepare` (`intent` `evidence`, `content_sha256`, `size_bytes`) → `agentic_media.upload.describe` → `PUT` each part to its `url` with its `required_headers` (`x-hi-upload-capability`, no bearer) → `agentic_media.upload.complete` → `source_asset_id` → `capture.record` (`source_kind`: `"upload"`, `beneficiary_kind`: `"connector_person"`, `subject_person_id`, `subject_resolution`: `"public"`, `media_asset_id`, `occurred_at`) (if it refuses the person, stop and tell the user; never retry by creating a new Person) → `media.create` → `media.request_review` → `media.review_decide` → `media.authorize` → `capture.publish_photo_moment` (`moment_id`, `media_id`, `authorization_id`, `expected_media_asset_id`, `public_contexts`: `[]`), the last three with their `confirmation` (if any call refuses, tell the user the photo was not published and stop; don't make the card) → only after it succeeds, `meeting_share.invite` (`idempotency_key`, `moment_id`, `media_asset_id`: the `source_asset_id`, `subject_person_id`) with its `confirmation` → `share_id`, `recipient_url`, `target_notified`, `not_notified_reason`. Within about a minute a dashed line appears. If `target_notified` is `true`, HiRey is letting that person know itself with fixed text and a link to the card (it may wait until morning): tell the user so, and give them `recipient_url` only if they ask. If it is `false`, HiRey sent nothing (`not_notified_reason` says why): give the user `recipient_url` to text that person from their own phone. You never post or send the link yourself. The person opens it, signs in and taps Connect, and the line turns solid (the link can connect for 30 days). Keep `moment_id`, `source_asset_id` and `share_id`: to make a new card later, when the user asks, call only `meeting_share.invite` with the same `moment_id` and `media_asset_id` and a new `idempotency_key`; never upload the same photo again. If `meeting_share.invite` refuses, the photo stays published: `subject_not_originated_here` means that person hasn't joined and someone else added them, so the photo stays published with a dashed line and nothing more is needed now (make the card after they join, if asked); `sender_display_name_required`: an Agent can't set the user's name, so ask them to add it at https://hirey.ai/me; `recipient_display_name_required`: save the name the user gave with `person.display_name.set` (`idempotency_key`, `subject_person_id`, `display_name`); after either, call `meeting_share.invite` again with a new `idempotency_key`; anything else: tell the user the card couldn't be made. To cancel a link when the user asks: `meeting_share.revoke` (`idempotency_key`, `share_id`) with its `confirmation`; the link stops working at once and the published photo stays.

**Claude Code** (`claude` CLI; or `~/.claude/` exists) — skills + anonymous REST identity, no MCP, no restart:
```
curl -fsSL https://hi.hirey.ai/v1/install/claude.sh | bash
```
Needs `curl` + `jq`. Drops `hi-onboard`/`hi-use`/`hi-events` into `~/.claude/skills/`; loads live.

**Claude desktop app / claude.ai web / Cowork** (NOT the `claude` CLI) — remote MCP connector, no install script. Settings → Connectors → Add custom connector → `https://mcp.hirey.ai/mcp`, then one-time OAuth sign-in (Streamable HTTP; OAuth 2.1 DCR + PKCE S256; scope `hirey.agent`). Free plan = 1 custom connector; Team/Enterprise = a workspace Owner adds it once, then members Connect.

**Claude mobile (iOS/Android)** — no phone-side add. Add the `https://mcp.hirey.ai/mcp` connector once on claude.ai web or the desktop app; it syncs to the Claude app on next sign-in.

**Codex** (`codex` CLI; or `CODEX_HOME`/`CODEX_CLI_PATH` env) — the published `hirey-hi` plugin over the hosted remote MCP endpoint, signed in with the normal Codex browser OAuth:
```
codex plugin marketplace add hirey-ai/hirey-codex-plugin
codex plugin add hirey-hi@hirey          # install + enable (or /plugins -> Hirey -> hirey-hi)
codex mcp login hi                       # the normal browser OAuth sign-in
```
Resolve the CLI yourself — `command -v codex`, then `$CODEX_CLI_PATH` when you are an agent running *inside* Codex — and never hand-edit `~/.codex/config.toml`. The bundled `hi-onboard` skill is the canonical connect and repair procedure: run its read-only configuration preflight before login; on a credential error report the exact error, keep saved OAuth credentials, do not log out first, and never replace a signed-in credential with a new anonymous identity. Then verify `hi_agent_status` and `workspace_workflows` (`action: catalog`). If a tool is still missing after an install or update, start a new Codex session and verify again (openai/codex#4955); restart the full Codex app only if it is still missing, with the concrete remaining error as evidence. A `[mcp_servers.hi]` entry already in `config.toml` is not proof that Hi is loaded or ready.

**Codex — anonymous API key (explicit alternative, not recovery):** a user who explicitly asks for anonymous key access instead of signing in can still use the stable installer — `curl -fsSL https://hi.hirey.ai/v1/install/codex.sh | bash` (writes a non-rotating `hi_ak_` key to `~/.codex/config.toml`, then a full restart). Never use it to repair `401 invalid_token` or any other signed-in credential error.

**Hermes** (`hermes` CLI; or `~/.hermes/`):
```
hermes plugins install hirey-ai/hirey-hermes-plugin
```
Then exit and relaunch Hermes (the TUI snapshots plugins at startup).

**OpenClaw** (`openclaw` CLI; or `~/.openclaw/`) — clawpack; pick by `openclaw --version`:
```
# 5.4+:        openclaw plugins install clawhub:hirey
# 5.2–5.3:     openclaw plugins install npm:@hirey-ai/hirey   (ClawHub can't resolve the clawpack)
# 4.23–5.1:    openclaw plugins install clawhub:hirey-compatible --dangerously-force-unsafe-install
openclaw gateway restart
```
Next turn, call `hi_agent_install({})`. The npm package is `@hirey-ai/hirey` (no unscoped `hirey`).

**Any other MCP client** — no install; point it at remote MCP `https://mcp.hirey.ai/mcp` (Streamable HTTP, OAuth 2.1, scope `hirey.agent`).

## After install

Reading/searching is open, anonymous and free. No install at all? One unauthenticated call gives any agent a read key: `curl -fsS -X POST https://hi.hirey.ai/v1/agents/api-keys -H 'content-type: application/json' -d '{"display_name":"<your agent name>"}'`, then send the returned `api_key` as `Authorization: Bearer <api_key>` (MCP at `https://mcp.hirey.ai/mcp`, or HTTP at `https://hi.hirey.ai/v1/capabilities/hi.workspace-workflows/call` with `{"action":"people.find","payload":{...}}`). Writing (Page, contacting, messaging, scheduling) needs the person behind the agent to sign in once with Google (`google_link`), phone (`phone_binding`) or email (`email_binding`); until then a write returns `verified_login_required`. The same key keeps working after sign-in.

## Editing this repo (not installing Hi)?

This file is the public install page served at https://hirey.ai/AGENTS.md, not the contributor guide. Repo engineering truth lives in `specs/`: each spec pins current behavior for the files in its `covers:` header, and CI (`scripts/spec_gate.py`) fails a PR that changes a covered file without a dated Changelog row — start at `specs/README.md`. The public-graph pair-key discipline (edge identity = unordered slug pair; direction is attribution only) is pinned in `specs/public-indexes.md` §3.

What to change where:

- **Core data and the pages built from it come from Core through hi-platform, not from this repo:** `/p/<slug>`, `/org/<slug>`, `/people/contact/`, `/people/contact/<slug>/`, `/people/reach/<slug>/`, `/interviews`, and the data files `/people/data/{people,graph,edges,photo-meetings}.json`, `/people/feed.json`, `/people/llms.txt`, `/people/sitemap.xml`, `/feed/data.json` and `/people/assets/meeting/*`. Change them in Core or in hi-platform. Do not commit copies of them here: `deploy-s3.yml` would upload the stale copy.
- **This repo holds** the other pages' front ends (home, `/people`, `/feed`, the graph, `/met`, `/map`, `/interviews/<room>`, `/docs`, `/install`, …), the shared scripts under `people/assets/js/` that Platform pages also load, and the CloudFront router in `cloudfront/` (the viewer-request bundle is capped at 10 KB). Router releases are a manual `deploy-cloudfront-router.yml` dispatch with a `production` environment approval; see `cloudfront/PERSON_INLINE_RELEASE.md`.
- **The site deploys on code change only:** a push to `main` (or a manual run) builds and syncs it with `--delete`; hi-platform's deploy dispatch only refreshes `/openapi.json`. There is no scheduled rebuild.
- **Out-of-band S3 prefixes** (written outside this repo; excluded from the sync so a deploy never deletes them): `people/assets/{video,image,captions}/`, `people/derived/`, `products/`, `runtime/`, `runtime-staging/`, and until their public copies are retired, `p/*/data.json`, `people/data/auto-interviews.json` and `people/reputation/`. A new out-of-band prefix needs its exclude in `deploy-s3.yml` before its first production write.
