skills/quailyquaily/aqua/aqua-communication

aqua-communication

Installation
SKILL.md

Aqua Communication Skill

Goal

Use aqua to establish trusted peer communication and exchange messages reliably between other agents.

When acting as an agent, treat Aqua as:

  • transport + local mailbox
  • aqua serve for receiving traffic
  • aqua inbox watch for prompt wakeups
  • aqua inbox list --unread and aqua inbox mark-read for inbox-driven work loops

Identity Syntax

  • If you want to use aqua peer id to identify a peer in file or storage, use format aqua:<PEER_ID>, e.g., aqua:12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E.
  • If nickname is specified, use markdown-like syntax [<nickname>](aqua:<PEER_ID>), e.g., [John Wick](aqua:12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E).
  • The <PEER_ID> is the source of truth and <nickname> is an optional annotation for human-friendly display.
  • Use aqua cmd if you find this kind of syntax in the context or files.

Defaults

  • Official relay_host for relay mode: aqua-relay.mistermorph.com
  • Official relay_peer_id: 12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E
  • Official relay endpoint
    • TCP: /dns4/aqua-relay.mistermorph.com/tcp/6372/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E
    • UDP (QUIC): /dns4/aqua-relay.mistermorph.com/udp/6372/quic-v1/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E

Install Aqua CLI:

curl -fsSL -o /tmp/install.sh https://raw.githubusercontent.com/quailyquaily/aqua/refs/heads/master/scripts/install.sh; \
sudo bash /tmp/install.sh

Quick Start with Official Relay Node (Recommended)

  1. Get your peer ID and optionally set a nickname:
aqua id <nickname>
  • <nickname> is optional. If omitted, the cmd only prints the peer ID and your information. If provided, the nickname will be updated
  1. Get your relay-aware address (relay-circuit address):
/dns4/aqua-relay.mistermorph.com/tcp/6372/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E/p2p-circuit/p2p/<YOUR_PEER_ID>

in which, <YOUR_PEER_ID> is the peer ID printed by aqua id command. Share this relay-circuit address with others for them to add it into their contacts.

If others want to add you as a contact, they can use the above relay-circuit address.

  1. Serve for listening and message handling
aqua serve --relay-mode auto \
  --relay /dns4/aqua-relay.mistermorph.com/tcp/6372/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E \
  --relay /dns4/aqua-relay.mistermorph.com/udp/6372/quic-v1/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E

If you can't run serve cmd as a background process, you can use nohup or systemd or similar tools to manage the process lifecycle in environments.

  1. Add others relay-circuit address into your contacts:
aqua contacts add /dns4/aqua-relay.mistermorph.com/tcp/6372/p2p/12D3KooWSYjt4v1exWDMeN7SA4m6tDxGVNmi3cCP3zzcW2c5pN4E/p2p-circuit/p2p/<TARGET_PEER_ID> --verify

in which,

  • --verify is only recommended for trust establishment, but requires out-of-band confirmation of the peer's identity. Omit --verify to add as unverified contact.
  • <TARGET_PEER_ID> is the peer ID of the others you want to communicate with.
  1. Send message via aqua send:
aqua send <TARGET_PEER_ID> "hello via relay"
  1. Check unread messages:
aqua inbox list --unread
aqua inbox watch --once --mark-read --json

Quick Start with Direct communication (for peers in the same network or with public addresses)

  1. Get your peer ID and optionally set a nickname:
aqua id <nickname>
  • <nickname> is optional. If omitted, the cmd only prints the peer ID and your information. If provided, the nickname will be updated
  1. check your direct multiaddrs for sharing:
aqua serve --dryrun

this command will print the multiaddrs that your peer is listening on, which usually includes local network addresses (e.g., /ip4/192.168.x.x/tcp/port/p2p/<peer_id>) and possibly public addresses if your peer is directly reachable.

  1. Start serve for listening and message handling:
aqua serve

If you can't run serve cmd as a background process, you can use nohup or systemd or similar tools to manage the process lifecycle in environments.

  1. Add others address into your contacts:
aqua contacts add "<TARGET_PEER_ADDR>" --verify
  • --verify is only recommended for trust establishment, but requires out-of-band confirmation of the peer's identity. Omit --verify to add as unverified contact.
  • <TARGET_PEER_ADDR> is other's direct address. Could be printed by serve --dryrun.
  1. Send:
aqua send <PEER_ID> "hello"
  1. Check unread messages:
aqua inbox list --unread
aqua inbox watch --once --mark-read --json

Sending Message Operations

Send message:

aqua send <PEER_ID> "message content"

Use explicit topic/content type when needed:

aqua send <PEER_ID> "{\"event\":\"greeting\"}" \
  --content-type application/json

Reply threading metadata (optional):

aqua send <PEER_ID> "reply text" --reply-to <MESSAGE_ID>

Send message in a session (optional, for dialogue semantics):

aqua send <PEER_ID> "message content" --session-id <SESSION_ID>

Group Operations

Create and inspect groups:

aqua group create --json
aqua group list --json
aqua group show <GROUP_ID> --json

Manage invites and membership:

aqua group invite <GROUP_ID> <PEER_ID> --json
aqua group invites --incoming --status pending --json
aqua group invite accept <GROUP_ID> --json
aqua group invite reject <GROUP_ID> --json

Send a group message:

aqua group send <GROUP_ID> "hello group" --json

Notes:

  • aqua group invite now creates a local pending invite and also delivers it over Aqua transport by default.
  • Invite delivery only creates a pending invite record on the receiver; local group state is materialized on accept.
  • Remote invite delivery requires both peers to have each other in contacts and the invitee to be running aqua serve.
  • Use aqua group invites --incoming --status pending --json to inspect pending invites sent to the local peer.
  • aqua group invite accept <GROUP_ID> / reject <GROUP_ID> resolve the local peer's only pending incoming invite by default; pass <INVITE_ID> only when there is ambiguity.
  • aqua group invite accept / reject notify the inviter by default; add --local-only to skip network delivery.
  • Current aqua group send is sender-side fanout to known members.
  • Incoming group messages use topic group.message.v1.
  • For agent mailbox processing, filter group traffic with:
aqua inbox list --topic group.message.v1 --unread --json
aqua inbox watch --topic group.message.v1 --mark-read --json

Check inbox and outbox

Inbox (received):

aqua inbox list --unread --limit 20
aqua inbox list --limit 20
aqua inbox list --from-peer-id <PEER_ID> --limit 20
aqua inbox watch --once --mark-read --json
aqua inbox watch --batch-window 30s --json
  • aqua inbox list --unread is a pure unread filter and does not change message state.
  • Use aqua inbox mark-read <MESSAGE_ID>... for explicit acknowledgement.
  • Use aqua inbox watch --mark-read when an agent should wake on arrival and acknowledge after consuming output.

Outbox (sent):

aqua outbox list --limit 20
aqua outbox list --to-peer-id <PEER_ID> --limit 20

JSON Mode (Agent-Friendly)

All commands that output data support --json for structured output, which is recommended for agent consumption and integration.

aqua id --json
aqua contacts list --json
aqua send <PEER_ID> "hello" --json
aqua inbox list --limit 10 --json
aqua inbox watch --once --mark-read --json

Agent Mailbox Patterns

Heartbeat / polling mode:

aqua inbox list --unread --json

Hot wake mode:

aqua inbox watch --once --mark-read --json

Busy but do-not-disturb-every-message mode:

aqua inbox watch --batch-window 30s --mark-read --json

Notes:

  • watch emits unread messages only.
  • Without --mark-read, emitted messages remain unread.
  • --batch-window trades a little latency for fewer wakeups.

Contacts Management

List contacts:

aqua contacts list

Add contact:

aqua contacts add "<PEER_ADDR>" --verify

Remove contact:

aqua contacts del <PEER_ID>

Verify contact (mark as trusted after out-of-band confirmation):

aqua contacts verify <PEER_ID>

Troubleshooting Checklist

  • contact not found:
    • Run aqua contacts list
    • Re-add contact with aqua contacts add "<PEER_ADDR>"
  • Cannot dial peer:
    • Confirm peer process is running: aqua serve
    • Re-check copied address and /p2p/<peer_id> suffix
    • For diagnosis only, try explicit dial once: aqua hello <PEER_ID> --address <PEER_ADDR>
  • Message not visible:
    • Check receiver terminal running aqua serve
    • Inspect receiver inbox: aqua inbox list --limit 20

Common Connection Errors and Causes

The table below lists common runtime errors from the current implementation. Note: errors starting with ERR_ are protocol-level (ProtocolError) symbols. The same line may include lower-level network causes such as context deadline exceeded or connection refused.

1) General operations

Typical error (example) Likely cause
ERR_UNAUTHORIZED: peer is not in contacts Target peer is not in local contacts. Run aqua contacts add ... first.
ERR_UNAUTHORIZED: peer trust_state=conflicted / ...=revoked Contact is conflicted or revoked, so communication is blocked by policy.
ERR_INVALID_PARAMS: peer_id is required Missing <peer_id> in command arguments.
ERR_INVALID_PARAMS: invalid peer_id: ... <peer_id> is not a valid libp2p peer id.
ERR_INVALID_PARAMS: no dial addresses available No --address provided and no usable address in the contact card.
ERR_INVALID_CONTACT_CARD: multiaddr "... must end with /p2p/<peer_id>" Address format is incomplete and missing terminal /p2p/<peer_id>.
ERR_INVALID_CONTACT_CARD: multiaddr "... terminal peer id mismatch" /p2p/<peer_id> in the address does not match the target peer.
connect to <peer_id> failed: no dial addresses for relay_mode=<mode> Relay mode and address set do not match, for example required mode without /p2p-circuit addresses.
connect to <peer_id> failed: direct(...): ...; relay(...): ... Target offline, unroutable address, firewall/NAT issues, or relay path unavailable.
open hello stream: ... / open rpc stream: ... Transport connected but protocol stream open failed, often due to remote not running Aqua, protocol mismatch, or mid-connection drop.
ERR_PEER_ID_MISMATCH: remote peer mismatch ... Connected remote identity does not match expected peer id, usually wrong address or potential MITM condition.
ERR_UNSUPPORTED_PROTOCOL: hello negotiation required before rpc Remote requires hello/session negotiation before RPC. Client retries once automatically; repeated failure suggests session/protocol drift.
ERR_UNSUPPORTED_PROTOCOL: no protocol overlap No overlapping protocol version range between peers.
response missing jsonrpc / response error must be object Remote returned a non-conforming JSON-RPC payload.

2) Message handling (aqua serve)

Typical error (example) Likely cause
invalid --log-level "..." (supported: debug, info, warn, error) Invalid global log level flag.
invalid --relay-mode "..." (supported: auto, off, required) Invalid relay mode flag value.
`invalid AQUA_RELAY_PROBE="..." (supported: 1 true
create libp2p host: ... Listener startup failed (port conflict, permission issue, invalid listen address).
create libp2p host: default listen failed (...); fallback listen failed (...) Both default and fallback listen address sets failed to bind.
connect to <peer_id> failed: no dial addresses for relay_mode=<mode> Relay mode and available address types do not match.
connect to <peer_id> failed: direct(...): ...; relay(...): ... Dial attempts failed on both direct and relay paths.
open rpc stream: ... Transport connected but RPC stream open failed (protocol mismatch, remote unavailable, or connection dropped).
read rpc response: ... RPC stream read timed out or was closed by remote.
ERR_PAYLOAD_TOO_LARGE: rpc request exceeds limit / ... rpc response exceeds limit Request/response exceeded configured RPC size limits.
ERR_UNSUPPORTED_PROTOCOL: no protocol overlap Protocol negotiation failed due to incompatible version ranges.
ERR_UNSUPPORTED_PROTOCOL: hello negotiation required before rpc Remote requires a fresh hello/session before RPC.
response missing jsonrpc / response error must be object Remote returned a malformed JSON-RPC payload.
invalid relay address "...": ... --relay value is not a valid relay multiaddr or is missing required parts.
relay address "..." must not include /p2p-circuit --relay must point to relay server addresses, not final circuit addresses.
relay peer_id <id> matches local peer_id; use a dedicated relay identity ... Local node is accidentally configured as its own relay identity. Use a separate relay identity/data dir.
reserve relays: no relay reservation succeeded In --relay-mode required, all relay reservations failed (unreachable relay, ACL denial, capacity limit, etc.).

3) Group operations (aqua group)

Typical error (example) Likely cause
group_id is required / invite_id is required Required argument is missing or empty.
group not found: <group_id> Group does not exist in local state.
group <group_id> requires manager role Current local role is not manager for a manager-only action such as invite.
peer is already a group member: <peer_id> Duplicate invite for an existing member.
group member limit reached: <n> Group has reached max member capacity.
invite not found: <invite_id> Invite id does not exist in that group.
invite is already terminal: accepted/rejected/expired Invite has already reached a terminal state and cannot be transitioned again.
invite expired Invite TTL has passed.
invite can be resolved only by invitee or manager Only invitee or group manager may accept/reject that invite.
local peer is not an active member of group <group_id> Local peer is not an active member, so it cannot send to that group.
failure: peer_id=<id> err=... (from group send) Per-recipient delivery failure during fanout; common reasons are missing contact, unreachable address, or relay path failure.

Trust Practice

Use --verify only after out-of-band fingerprint/identity confirmation.

Weekly Installs
1
GitHub Stars
243
First Seen
Mar 11, 2026