원클릭으로
find-person
Look up a person by name; pick source='household' for user_id, 'contacts' for chat/email/postal.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Look up a person by name; pick source='household' for user_id, 'contacts' for chat/email/postal.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create a new contact (person or business) with ALL its channels and address in one call.
Fetch the full body and metadata of a single email by message_id.
Record a new bill / recurring expense
Create a new calendar event in Yorik's local calendar
Attach a postal address (home, work, billing, shipping) to an existing contact.
Attach a channel (email, phone, whatsapp, signal, sms, website, social) to a contact.
| name | find_person |
| description | Look up a person by name; pick source='household' for user_id, 'contacts' for chat/email/postal. |
| when_to_use | Use this for ANY "find X" / "wer ist X?" / "termin mit X" / "schreib X" intent. Choose `source` by what you'll DO with the result, not by who you think the person is. The model used to flip between find_user and find_contact and get it wrong; one tool with an enum removes the choice. ┌───────────────────────────────┬────────────────────┬─────────────────────────────────┐ │ Your next action │ source │ What you get back │ ├───────────────────────────────┼────────────────────┼─────────────────────────────────┤ │ add_calendar_event with │ "household" │ user_id — pass as │ │ attendee_user_ids / RSVPs │ │ attendee_user_ids=[id] │ │ │ │ │ │ whatsapp_draft, email_draft, │ "contacts" │ chat_jid, email, postal, + │ │ compose_draft (letters) │ │ contact_id (NOT a user_id) │ │ │ │ │ │ Don't know yet / user just │ "auto" (default) │ both household + contacts; │ │ asked "wer ist X?" │ │ each row tagged with │ │ │ │ `source` so you pick at │ │ │ │ quote-time │ └───────────────────────────────┴────────────────────┴─────────────────────────────────┘ A `contact_id` is NEVER a valid `attendee_user_ids` value — different tables, overlapping integer ranges. Always read the `source` field on the row before reusing `id`. If multiple candidates matched, STOP and ask the user. Don't pick the first one. Contact results auto-render a picker card; household results — list them with role + name and ask. AMBIGUOUS RELATIONAL DESCRIPTOR ("my friend", "der Klempner", "Oma"): do NOT ask for a name in prose. 1. Try find_person(query="<descriptor>", source="contacts") — matches the relation field. 2. If 0 hits, run list_contacts_for_picking's two-call ranking flow (defer_card=true → ranked_picks=[…]). 3. Aim for 10 picks; shorter lists pad with neutral recent contacts. |
| inputs | {"query":{"type":"string","required":false,"description":"Free-text search. Matches against name / first_name / last_name /\nemail (and contact aliases when source includes contacts). Omit\nto list everyone in the chosen source (typically only useful for\nsource='household' to enumerate logged-in users).\n"},"source":{"type":"string","required":false,"default":"auto","description":"Where to look: 'household' (user_profiles, returns user_id for\nattendees), 'contacts' (address book, returns chat_jid/email/\npostal for messaging), 'auto' (both, with per-row source field).\n"},"kind":{"type":"string","required":false,"description":"Contacts-only filter — 'person' or 'business'. Ignored for\nhousehold lookups.\n"},"role":{"type":"string","required":false,"description":"Household-only filter — 'admin' | 'member' | 'child' | 'employee'\n| 'viewer'. Ignored for contact lookups.\n"},"status":{"type":"string","required":false,"default":"any","description":"Contacts-only — 'active' | 'pending' | 'spam' | 'archived' | 'any'.\nDefault 'any' returns active + pending, skips spam + archived.\n"},"channel_kind":{"type":"string","required":false,"description":"Contacts-only channel lookup. Pair with channel_value for an\nindexed (kind, value) hit — e.g. channel_kind='phone',\nchannel_value='+493012345'.\n"},"channel_value":{"type":"string","required":false},"limit":{"type":"integer","required":false,"default":10}} |
| outputs | {"results":{"type":"array","description":"Each row has `source` ('household'|'contacts') and its natural fields.\nHousehold: {source, id (=user_id), name, first_name, last_name, role, email}.\nContacts: {source, id (=contact_id), display_name, relation, kind, channels[], addresses[]}.\nRead `source` BEFORE using `id` anywhere — the two id spaces overlap.\n"},"count":{"type":"integer"},"ambiguous":{"type":"boolean","description":"True if multiple candidates matched (calls for user disambiguation)."}} |
| cost | 1-2 indexed SELECTs depending on source |
| permissions | ["admin","member","restricted"] |
| side_effects | May emit a contact_picker UI card when contact results are ambiguous (existing behavior inherited from find_contact). No DB writes. |
| tags | ["users","contacts","lookup","read"] |
Single lookup tool, two sources, one decision point: pick source by the
action you'll take with the result.
Replaced the old find_user + find_contact pair (since removed from the
registry). The whole reason for the merge was to dissolve the model's
"which of two near-identical lookup tools?" choice into the much easier
"which source enum?" choice.
source='household', get user_id, pass as
attendee_user_ids to add_calendar_event so Anna gets a real
RSVP notification.source='contacts', get the postal
address, hand off to compose_check_recipient → compose_draft.source='auto', see if she's a household user
AND/OR a contact, answer the user based on what's there.