Talk to another Oracle agent via contacts + threads. Use when user says "talk to", "message", "chat with", or wants to communicate with another agent (e.g. "talk to pulse", "message neo"). Do NOT trigger for OracleNet social feed (use /oraclenet), skill management (use /oracle), or family registry (use /oracle-family-scan).
SKILL.md
/talk-to - Agent Messaging
Send messages to agents via Oracle threads. Each agent has a persistent channel thread.
Messaging consolidation (2026-07-06): /hey, /contacts, /mailbox, and /inbox were
archived to the zombie tier — this skill is the one messaging verb now. For real-time
tmux pings use maw hey directly (or --maw here). Archived skills remain installable
via arra install -s <name>.
Usage
/talk-to arthur "What's your status?" # one-shot message
/talk-to arthur --new "Hey, starting fresh" # skip lookup, create new thread
/talk-to arthur loop ask about their work # autonomous conversation
/talk-to #42 "follow up on this" # post to thread by ID
/talk-to --list # show channels
/talk-to arthur --maw "quick ping" # force maw transport (real-time tmux)
/talk-to arthur --thread "async question" # force MCP thread transport
/talk-to arthur --inbox "offline message" # force inbox transport (file write)
Mode 0: No arguments
If ARGUMENTS is empty, show usage help then run --list.
Step 0: Contacts Lookup
Always read contacts first. This is the source of truth for agent routing.
date "+🕐 %H:%M %Z (%A %d %B %Y)"
CONTACTS="$(pwd)/ψ/contacts.json"
if [ ! -f "$CONTACTS" ]; then
# Fallback path
CONTACTS="$(pwd)/.oracle/contacts.json"
fi
if [ -f "$CONTACTS" ]; then
MAW=$(jq -r ".contacts.\"$AGENT\".maw // empty" "$CONTACTS")
INBOX=$(jq -r ".contacts.\"$AGENT\".inbox // empty" "$CONTACTS")
THREAD=$(jq -r ".contacts.\"$AGENT\".thread // empty" "$CONTACTS")
REPO=$(jq -r ".contacts.\"$AGENT\".repo // empty" "$CONTACTS")
NOTES=$(jq -r ".contacts.\"$AGENT\".notes // empty" "$CONTACTS")
FOUND_IN_CONTACTS=true
else
FOUND_IN_CONTACTS=false
fi
If agent not found in contacts AND not found in maw ls:
I don't know "{agent}".
/contacts add {agent} — register transport info
/talk-to {agent} --thread "message" — try MCP thread anyway
Offer /contacts add first. If user insists, fall through to MCP thread.
Transport Selection
Flag
Transport
Best For
(none)
auto — detect best
Default
--maw
maw hey (tmux sendkeys)
Real-time, local fleet, low latency
--thread
MCP oracle_thread
Async, persistent, cross-machine
--inbox
File write to ψ/inbox/
Offline, no maw/MCP needed
Auto-detect logic (when no flag):
Check ψ/contacts.json → has maw field? → use maw hey
No contacts? → maw ls 2>/dev/null | grep -q "{agent}" fallback → use maw hey
Neither? → use MCP thread (async, persistent)
# Auto-detect: contacts-first, maw ls fallback
if [ -n "$MAW" ]; then
echo "USE_MAW (from contacts: $MAW)"
elif maw ls 2>/dev/null | grep -q "{agent}"; then
echo "USE_MAW (from maw ls)"
else
echo "USE_THREAD"
fi
Replying to a message another oracle sent you (#434)
A ping arrives in your context looking like [m5:digger] …. The reflex is to
answer in your own transcript — but that text goes to Nat, not to digger, who is
sitting in a different pane waiting. Reply with maw hey or the conversation is
one-sided and nobody notices for hours.
maw hey <their-oracle-name> 'your reply' # name, not a pane id
Never reply to a pane id.maw peek %3001 works, so it is tempting to paste
that same %3001 into maw hey — it hard-errors (bare target '%3001' not found locally). Pane ids are a peek-only handle. maw ls -v is the source of truth
for targets; a bare maw ls | grep finds the row but not the addressable name,
which is why the auto-detect above should be treated as a hint, not an answer:
maw ls -v | grep -i <name> # resolves the real target
maw hey <target> ping --dry-run # confirm it resolves BEFORE sending
--dry-run is the cheap check. It costs nothing and catches a wrong target
before the message goes somewhere confusing.
When using --maw:
Compose message from intent
Use contacts maw name if available: maw hey {MAW or agent-oracle} '{message}'
Optionally maw peek {agent} to check response
Confirm: Sent via maw to {agent}
When using --inbox:
Compose message from intent
Check contacts for inbox path — if empty, error: No inbox path for {agent}. Run /contacts show {agent}
Write message file:
SELF="$(basename $(pwd) | sed 's/-oracle$//')"
echo "$MESSAGE" > "$INBOX/$(date +%Y%m%d_%H%M)_from_${SELF}.md"
Confirm: Dropped to {agent}'s inbox
When using --thread (or auto-detected thread):
Fall through to Mode 3 (one-shot) below.
Routing
Pattern
Use
channel:{agent}
Persistent per-agent channel
topic:{agent}:{slug}
Topic-specific thread (with --topic)
#{id}
Direct thread reference by ID
Mode 1: --list
arra_threads() (no status filter)
Filter titles starting with channel: or topic:, exclude closed
arra_thread_read({ threadId }) → show any agent responses
Confirm: Posted to channel:{agent} (thread #{id})
Mode 4: loop (autonomous conversation)
Like Ralph loop — AI drives the conversation autonomously. No user prompts between turns.
Find or create thread (channel:{agent}, or --new to skip lookup)
Compose opening message from user's intent and post it
Autonomous loop (max 10 iterations):
a. arra_thread_read({ threadId }) — check for new messages
b. If agent responded: read their response, compose a thoughtful follow-up, post it
c. If no new response: compose a follow-up question or probe deeper, post it
d. After each exchange, briefly note what you learned
e. Stop when: enough insight gathered, conversation circling, or 10 iterations hit
Notify (once, after opening message):
Bash maw hey {MAW or agent-oracle} 'Thread #{id} from {self}: {preview}'