Skip to content

Repository files navigation

Inkbox OpenClaw Plugin

OpenClaw, now with a phone



Give your OpenClaw agent its own Inkbox identity:
a mailbox, iMessage, a phone number for calls and SMS, voice, contacts, notes, and an internet address.
Keep OpenClaw reachable from anywhere without forking OpenClaw.

Email · Calls · SMS / MMS · iMessage · Contacts · Notes



Status: outbound tools, read tools, bundled skills, setup wizard, doctor checks, SMS/MMS batching, 1:1 and group text conversations, inbound email/SMS/iMessage/voice, realtime phone calls, post-call actions, and package-included skills are implemented. ClawHub publishing is still pending.

Prerequisites

  • An installed OpenClaw agent, 2026.5.19 or newer. Start at openclaw.ai or follow the OpenClaw install docs.
  • The recommended OpenClaw installer for macOS, Linux, or WSL2:
curl -fsSL https://openclaw.ai/install.sh | bash
openclaw --version

Then onboard OpenClaw and configure a model provider. We recommend using either an OpenAI API key or a ChatGPT/Codex subscription:

openclaw onboard
openclaw configure

If you already manage Node yourself, the OpenClaw docs also support installing the CLI with npm before running the same onboard/configure commands:

npm install -g openclaw@latest
  • An Inkbox account or API key. openclaw inkbox setup can guide a new agent identity through signup/setup.

Quick Start

Run these from the plugin checkout after the OpenClaw prerequisite above is installed:

git clone https://github.com/inkbox-ai/openclaw-plugin.git
cd openclaw-plugin
npm install
npm run build
openclaw --version
openclaw plugins install -l --force --accept-capabilities ./

Configure Inkbox:

openclaw inkbox setup
openclaw inkbox doctor

The setup wizard writes channels.inkbox into the active OpenClaw profile and adds the Inkbox tool group to the profile's tool policy.

Set up an assigned identity without prompts

An agent can complete setup after a human assigns an existing identity handle, API base URL, and credential. Use the local plugin installation flow above, but inspect the checkout before installing it into OpenClaw:

  1. Confirm the clone's remote, current revision, and clean working tree.
  2. Review package.json, its scripts, and the declared and locked dependencies before running npm install.
  3. Run npm install and npm run build, review the installed dependency summary and build output, and check the working tree for unexpected changes.
  4. Only then run the local openclaw plugins install -l --force --accept-capabilities ./ command.

First inspect the checkout and manifest. Also review package-lock.json before continuing:

git remote get-url origin
git log -1 --oneline
git status --short --branch
npm pkg get scripts dependencies devDependencies peerDependencies

After that review, install the dependencies and build. Inspect the dependency summary, build output, and working tree before continuing:

npm install
npm ls --depth=0
npm run build
git status --short

Only install the reviewed local build into OpenClaw when those checks have the expected results:

openclaw plugins install -l --force --accept-capabilities ./

Keep the credential out of source control, project instructions, command arguments, and transcripts. Place it in the private process environment as INKBOX_API_KEY; if entering it in a terminal, read it without echoing:

read -rsp 'Inkbox API key: ' INKBOX_API_KEY && printf '\n'
export INKBOX_API_KEY
openclaw inkbox bootstrap --identity '<handle>' --base-url '<url>' \
  --voice-ai --rotate-signing-key --start-gateway
unset INKBOX_API_KEY

bootstrap is non-interactive. It validates and preserves the exact assigned identity, scopes down an admin key before saving it, preserves existing Voice AI settings, updates the active OpenClaw profile, and starts, restarts, or installs the gateway service. When it starts the gateway, it disables the optional startup agent prewarm so bootstrap can finish safely from inside a live OpenClaw session; the first real inbound turn may pay the one-time cold-start cost. Signing-key replacement is explicit because it transfers verified webhook delivery away from gateways using the previous key.

The command prints secret-redacted JSON and is safe to resume:

  • For "status": "configured", run openclaw inkbox doctor and confirm the configured identity and live connection are healthy.
  • For "status": "requires_human", show the human each requested entry in humanActions. After the human completes those actions, restore INKBOX_API_KEY privately and rerun the same bootstrap command with the same assigned handle; do not create or select a different identity.
  • For "status": "error", inspect the redacted error and completed actions, diagnose the credential, assigned handle, base URL, local config, or gateway state as indicated, and correct that cause. Then restore INKBOX_API_KEY privately and rerun the same bootstrap command with the same assigned handle. openclaw inkbox doctor and, for gateway errors, openclaw gateway status provide focused diagnostics.

Always unset the transient INKBOX_API_KEY after each attempt. Bootstrap saves the resulting agent-scoped credential in the active OpenClaw profile; never copy credentials into this checkout or any other project file.

Docker test shell

This is a manual testing-only playground; it is not published and is not an automated CI or release artifact. The included image preinstalls OpenClaw and builds this checkout. It contains no credentials:

docker build -t inkbox-openclaw-plugin .
docker run -d --name inkbox-openclaw \
  -e OPENAI_API_KEY="$OPENAI_API_KEY" \
  inkbox-openclaw-plugin
docker exec -it inkbox-openclaw bash

Inside the container, install the already-built local plugin and run setup:

openclaw plugins install -l --force --accept-capabilities /opt/inkbox-plugin-src
openclaw inkbox setup
openclaw inkbox doctor
openclaw gateway run

OpenClaw requires the explicit install acknowledgment because the plugin's gateway setup helper invokes the OpenClaw CLI to start, restart, or install the gateway service.

Start the gateway:

openclaw gateway run

Keep that process running. On startup the plugin opens an Inkbox tunnel, configures mail/text/iMessage webhook subscriptions and the incoming-call URL, and routes inbound email, SMS, iMessage, and calls into OpenClaw sessions.

Restart the gateway after changing Inkbox config, updating the plugin, or re-running setup:

openclaw gateway restart

If you started the gateway in the foreground with openclaw gateway run, press Ctrl+C in that terminal and start it again:

openclaw gateway run

Setup Wizard

openclaw inkbox setup walks the current OpenClaw profile through Inkbox configuration:

  1. Authenticates to Inkbox or uses the API key already present in config.
  2. Resolves or creates the Inkbox agent identity for this OpenClaw agent.
  3. Stores an agent-scoped API key, the identity handle, and webhook signing key in channels.inkbox.
  4. Offers to enable iMessage for the agent, then optionally provisions a local SMS + voice phone number.
  5. Shows a native Phone call voice stack selector with Inkbox Voice AI, OpenAI Realtime API, and Inkbox TTS/STT.
  6. For Voice AI, configures contact-scoped or YOLO authority using an admin-scoped key only when authority must change; the admin credential is never persisted. For Realtime, validates the OpenAI API key and returns to the three choices if validation fails.
  7. Points mailbox, text, iMessage, and call.ended events at separate canonical subscriptions. Local voice stacks use auto_accept with the gateway media WebSocket; Voice AI uses hosted_agent.
  8. Prints the final mailbox/phone summary.

If setup provisions a new local phone number, it waits for any inbound SMS START to that number before finishing. It also seeds ~/.openclaw/inkbox/identity-state.json so openclaw inkbox doctor can show useful channel state.

Inkbox reachability is controlled server-side with mailbox and phone contact rules in the Inkbox Console. The plugin does not create a second local inbound allowlist unless you explicitly set allowedInboundContactIds.

Manual Config

Preferred config shape:

{
  "channels": {
    "inkbox": {
      "apiKey": "ApiKey_xxxxxxxxxxxx",
      "identity": "my-agent-handle",
      "signingKey": "whsec_xxxxxxxxxxxx",
      "voiceStack": "inkbox_voice_ai",
      "voiceAiAuthorityMode": "contact_scoped",
      "voicemailDetection": "enabled"
    }
  },
  "tools": {
    "allow": ["inkbox"]
  }
}

Equivalent config commands:

openclaw config set channels.inkbox.enabled true --strict-json
openclaw config set channels.inkbox.apiKey "ApiKey_xxxxxxxxxxxx"
openclaw config set channels.inkbox.identity "my-agent-handle"
openclaw config set channels.inkbox.signingKey "whsec_xxxxxxxxxxxx"
openclaw config set tools.allow '["inkbox"]' --strict-json
openclaw config validate

Env vars are also supported by the plugin and CLI:

export INKBOX_API_KEY="ApiKey_xxxxxxxxxxxx"
export INKBOX_IDENTITY="my-agent-handle"
export INKBOX_SIGNING_KEY="whsec_xxxxxxxxxxxx"
export INKBOX_BASE_URL="https://your-inkbox-api.example"

Legacy plugin-scoped config under plugins.entries.inkbox.config still works, but new installs should use channels.inkbox.

Optional Tools

"inkbox" in tools.allow enables the required tools. Optional tools must be listed by name.

Common full-access smoke allowlist, excluding vault plaintext tools:

openclaw config set tools.allow '[
  "inkbox",
  "inkbox_forward_email",
  "inkbox_place_call",
  "inkbox_mark_emails_read",
  "inkbox_list_texts",
  "inkbox_get_text",
  "inkbox_mark_text_read",
  "inkbox_mark_text_conversation_read",
  "inkbox_imessage_triage_number",
  "inkbox_list_imessage_assignments",
  "inkbox_send_imessage_reaction",
  "inkbox_mark_imessage_conversation_read",
  "inkbox_update_note",
  "inkbox_delete_note",
  "inkbox_list_mail_contact_rules",
  "inkbox_list_phone_contact_rules",
  "inkbox_list_note_access",
  "inkbox_grant_note_access",
  "inkbox_revoke_note_access",
  "inkbox_whoami"
]' --strict-json

Add vault tools only when the identity has vault access and the gateway environment has the vault unlock key:

export INKBOX_VAULT_KEY="..."
openclaw config set tools.allow '[
  "inkbox",
  "inkbox_credentials_list",
  "inkbox_credentials_get_login",
  "inkbox_credentials_get_api_key",
  "inkbox_credentials_get_ssh_key",
  "inkbox_totp_code"
]' --strict-json

Phone Call Voice Stacks

openclaw inkbox setup offers three explicit choices:

  1. Inkbox Voice AI handles calls on behalf of the agent. OpenClaw receives the final transcript and open post-call actions after hangup. Outbound calls use mode=hosted_agent, include a task reason, and intentionally omit a per-call authority override so the saved Voice AI default applies.
  2. OpenAI Realtime API uses your validated OpenAI API key. The realtime voice agent can consult OpenClaw for complex work.
  3. Inkbox TTS/STT keeps the OpenClaw agent in the spoken loop through Inkbox speech services, with increased latency.

Plain-text output from a Voice AI post-call turn is suppressed because the call has ended; requested side effects run through normal tools. Completion receipts are durable and unfinished calls are replayed after gateway restart.

Agent runner compatibility

Use the native OpenClaw runner for hosted-call settlement, A2A progress, and silent cross-channel completion. These features depend on the host's before_agent_run and model-call lifecycle hooks; Codex and other external runners do not emit the same lifecycle. Recent OpenClaw versions default official OpenAI models to the Codex runner, so select the native runner explicitly for your chosen model, for example:

openclaw config set 'agents.defaults.models["openai/gpt-5.6-sol"].agentRuntime.id' openclaw

Use your configured model key in place of the example. Inkbox setup does not change your model or override an explicitly chosen runner. This setting concerns the main agent, not the separate realtime voice provider.

Setup also enables OpenClaw's plugins.entries.inkbox.hooks.allowConversationAccess permission. The plugin needs this host permission to bind channel sends and Voice AI completions to their exact runs before accepting side-effecting tool evidence, and to associate A2A progress with its worker run. Conversation bodies are not stored in the completion registry or replay journal. For manual configuration, explicitly set plugins.entries.inkbox.hooks.allowConversationAccess: true to enable those lifecycle hooks, native approval routing, and confirmation that background group context was consumed. Without that permission, unconfirmed background context remains retained and may appear in later turns; the plugin does not enable the permission automatically outside setup.

OpenAI Realtime

Calls can use raw Inkbox call media through OpenAI Realtime. The call transport negotiates HD voice as mono 16 kHz PCM16LE, resampled continuously to and from the realtime provider’s 24 kHz PCM format. Older call endpoints remain compatible with 8 kHz μ-law audio. OpenAI GA Realtime requires an OpenAI API key; ChatGPT/Codex subscription OAuth profiles are not used for this path. During openclaw inkbox setup, the wizard looks for an existing OpenAI API key in channels.inkbox.voiceRealtime.providers.openai.apiKey, INKBOX_REALTIME_API_KEY, an OpenClaw openai API-key auth profile, or OPENAI_API_KEY. Environment keys are setup-time discovery inputs unless the wizard validates and persists them into channels.inkbox.voiceRealtime.providers.openai.apiKey. If it finds one, it asks whether to enable Realtime calls, validates access to gpt-realtime-2, and stores the validated key in the Inkbox Realtime provider config. If no key is found, it prompts for one and validates it before enabling Realtime.

export INKBOX_REALTIME_API_KEY="sk-..."
openclaw configure
openclaw inkbox setup
openclaw gateway run

Realtime calls receive the agent's Inkbox handle, mailbox, phone number, caller contact metadata, and outbound-call purpose before greeting. The realtime voice model can call openclaw_agent_consult, inkbox_register_post_call_action, inkbox_edit_post_call_action, inkbox_delete_post_call_action, and inkbox_hang_up_call. If validation fails during setup, the wizard returns to the three voice-stack choices. An explicitly configured openai_realtime stack does not silently fall back to another stack at runtime.

Optional realtime overrides:

openclaw config set channels.inkbox.voiceRealtime.provider openai
openclaw config set channels.inkbox.voiceRealtime.model gpt-realtime-2
openclaw config set channels.inkbox.voiceRealtime.voice cedar

Disable realtime:

openclaw config set channels.inkbox.voiceRealtime.enabled false --strict-json

Two calling lines

Calls — inbound and outbound — can run over either of two lines, and the agent picks the one that matches the channel it's talking on:

  • The dedicated phone number. The agent's own number (the same line SMS uses). Outbound calls present this number; inbound calls to it ring the agent.
  • The shared Inkbox iMessage line. The agent can also place and receive voice calls with a person it's connected to over iMessage, over the same shared line that person already messages. The underlying number is never surfaced — Inkbox resolves it from the iMessage connection — and it only works for people already connected over iMessage (an unknown caller is rejected; an outbound call with no connection is refused).

Inbound answering is configured once per identity (hosted_agent for Inkbox Voice AI, otherwise auto_accept to open the call bridge WebSocket), so a single setting governs both lines. Outbound, the agent sets origination on inkbox_place_call (dedicated_number / shared_imessage_number), or omits it — the plugin then uses whichever line is the only one available, or the line matching the conversation's channel when both are.

iMessage

iMessage works differently from SMS: the agent does not get its own iMessage number. People connect to the agent through the Inkbox iMessage router, and each connected person gets a dedicated thread with the agent.

  1. Enable iMessage for the agent during openclaw inkbox setup (or later by re-running it). Enablement is stored on the Inkbox identity, not in local config.
  2. From an iPhone, text the connect command (for example connect @my-agent-handle) to the Inkbox iMessage router number. The wizard prints both, and the agent can also share them via the inkbox_imessage_triage_number tool.
  3. Inkbox texts back from the number assigned to that conversation. Send any first message there — the agent can only reply after you message it first (recipient-first; there is no cold outreach over iMessage).
  4. The setup wizard waits for that first message and replies with a welcome confirming the channel. From then on, the gateway routes the thread into the same contact-keyed OpenClaw session as email/SMS/voice, and the agent replies over iMessage in that thread.

If a person disconnects the agent, outbound sends to that conversation fail until they reconnect through the router and message the agent again. Conversation rows expose assignmentStatus (active/released) so the agent can see this, and inkbox_list_imessage_assignments lists who is currently connected. Outbound delivery transitions (imessage.sent, imessage.delivered, imessage.delivery_failed) arrive as webhooks and are logged by the gateway without waking the agent, matching the SMS lifecycle handling.

While the agent composes a reply, the recipient sees a typing indicator — the gateway pulses it until the response sends. In automatic group mode and direct conversations, a question tapback is treated as a request for clarification. Other tapbacks are ambient events: normally nothing is sent; if a response is warranted, the agent sends it explicitly into the same conversation. In group mention mode, unmentioned reactions remain background context without waking the agent.

Once someone is connected over iMessage, the agent can also place and receive voice calls with them over that same shared line — see Two calling lines. This works even for an agent that has no dedicated phone number.

CLI

openclaw inkbox setup
openclaw inkbox doctor
openclaw inkbox whoami
openclaw doctor
openclaw status

Useful OpenClaw commands while iterating:

openclaw config file
openclaw config get channels.inkbox
openclaw config validate
openclaw plugins list
openclaw skills list
openclaw logs

Optional provider-specific auth examples:

openclaw models auth login --provider openai --set-default
openclaw models auth login --provider openai-codex --set-default

Smoke Test

After the gateway prints [gateway] ready, [inkbox] tunnel open, mail/text subscriptions configured, and the incoming-call URL wired:

  1. Run openclaw inkbox doctor.
  2. Text START to the agent's Inkbox phone number from every phone the agent should text.
  3. Send the agent an SMS and verify it replies in the same SMS thread.
  4. If iMessage is enabled, connect via the Inkbox iMessage router, message the agent, and verify it replies in the same iMessage thread.
  5. Send the agent an email and verify it replies from its Inkbox mailbox.
  6. Call the agent phone number and ask for its handle, email, and phone.
  7. Ask during a call for a post-call SMS or email follow-up, then verify it sends after hangup.
  8. Ask the agent to save a contact and an Inkbox note, then ask it to read them back.

Config Reference

Field Required Default Description
apiKey yes - Agent-scoped Inkbox API key. Admin keys are accepted by setup only so it can mint an agent-scoped key.
identity yes - Inkbox agent identity handle.
signingKey inbound - Webhook HMAC secret. Required for inbound email/SMS/iMessage/calls.
baseUrl no SDK default Override Inkbox API base URL.
tunnelName no identity handle Override Inkbox tunnel name.
publicUrl no - Public OpenClaw URL. If omitted, the plugin opens an Inkbox tunnel.
allowedRecipients no - Outbound recipient allowlist for messaging targets and A2A Agent Card URLs. Empty means no local outbound filtering.
allowedInboundContactIds no - Optional local inbound allowlist by Inkbox contact UUID. Empty means Inkbox contact rules decide reachability.
includeContactMemories no true Include memories from the matched contact as background context for inbound email, messaging, reactions, and calls. Set false to disable them.
a2aProgressIntervalSeconds no 180 Send a short nonterminal progress update while serving an A2A task at this cadence. Set to 0 to disable periodic updates. The immediate receipt includes the configured frequency.
sms.batchDelayMs no 0 Inbound SMS and iMessage fragment batching window.
voiceStack no legacy-compatible inkbox_voice_ai, openai_realtime, or inkbox_tts_stt. Setup always writes an explicit value.
voiceAiAuthorityMode Voice AI saved server value Informational local copy of the selected contact_scoped or yolo authority.
voicemailDetection no enabled Outbound-call voicemail detection policy. CI should set disabled.
voiceTranscriptCoalesceMs no plugin default Non-realtime voice transcript coalescing window.
voiceAgentPrewarm no plugin default Prewarm the voice path when the gateway starts.
voiceRealtime.enabled no auto Use raw phone media with an OpenClaw realtime voice provider. Set false to force Inkbox STT/TTS.
voiceRealtime.provider no openai Realtime provider id, for example openai.
voiceRealtime.model no provider default Realtime model override, for example gpt-realtime-2.
voiceRealtime.voice no cedar Realtime voice name.
voiceRealtime.toolPolicy no owner Tool policy for realtime openclaw_agent_consult.
voiceRealtime.consultPolicy no substantive When realtime calls should consult the main OpenClaw agent.
voiceRealtime.providers.openai.apiKey no - OpenAI API key validated by setup and used for Realtime calls.
voiceRealtime.fallbackToInkboxSttTts no true Fall back to Inkbox STT/TTS when realtime is unavailable.
vault.keyEnvVar no INKBOX_VAULT_KEY Env var containing the vault unlock key.

Tools

Required by default:

  • Outbound: inkbox_send_email, inkbox_send_sms, inkbox_send_imessage
  • A2A client: inkbox_a2a_call, inkbox_a2a_check, inkbox_a2a_reply, inkbox_list_a2a_tasks, inkbox_list_a2a_messages
  • A2A history supports optional direction, requester, worker, task/context, state/role, keyword, timestamp, cursor, and limit filters as applicable.
  • Inbound A2A tasks are delivered into isolated context sessions. During those turns, inkbox_a2a_complete, inkbox_a2a_ask_caller, and inkbox_a2a_fail commit the task outcome explicitly.
  • The plugin pins @inkbox/sdk 0.7.6.
  • Email reads: inkbox_list_unread_emails, inkbox_list_emails, inkbox_get_email, inkbox_get_email_thread
  • SMS reads: inkbox_list_text_conversations, inkbox_get_text_conversation (conversation-ID aware, groups included by default)
  • iMessage reads: inkbox_list_imessage_conversations, inkbox_get_imessage_conversation
  • Voice reads: inkbox_list_calls, inkbox_list_call_transcripts
  • Contacts: inkbox_lookup_contact, inkbox_get_contact, inkbox_list_contacts, inkbox_create_contact, inkbox_update_contact, inkbox_delete_contact
  • Notes: inkbox_list_notes, inkbox_get_note, inkbox_create_note

Optional:

  • Outbound: inkbox_forward_email, inkbox_place_call
  • Lifecycle: inkbox_mark_emails_read, inkbox_list_texts, inkbox_get_text, inkbox_mark_text_read, inkbox_mark_text_conversation_read, inkbox_mark_imessage_conversation_read
  • iMessage: inkbox_imessage_triage_number, inkbox_list_imessage_assignments, inkbox_send_imessage_reaction
  • Notes: inkbox_update_note, inkbox_delete_note
  • Contact rules: inkbox_list_mail_contact_rules, inkbox_list_phone_contact_rules; manage changes in the Inkbox Console
  • Note access: inkbox_list_note_access, inkbox_grant_note_access, inkbox_revoke_note_access
  • Vault: inkbox_credentials_list, inkbox_credentials_get_login, inkbox_credentials_get_api_key, inkbox_credentials_get_ssh_key, inkbox_totp_code
  • Diagnostic: inkbox_whoami

Send and email-forward tools accept optional completeSilently: true when the send is the final requested action and no acknowledgment is wanted. Successful sends then end the turn without an extra source-channel reply. Leave it unset when more work or a reply remains; failed sends never silently complete.

Group replies and Companion mode

Group SMS and iMessage participants share a conversation session, including reactions. Different groups and direct conversations remain separate. Automatic email replies use the stored message's reply-all route, preserving visible To/CC and threading without adding BCC recipients or the agent itself. Explicit new-email tools still use the recipients you specify.

The setup wizard exposes these independent choices for new or existing identities:

Setting Values Default
channels.inkbox.groupReplyMode / INKBOX_GROUP_REPLY_MODE auto, mention auto
channels.inkbox.companionResponseMode / INKBOX_COMPANION_RESPONSE_MODE safe, relaxed safe

Saved account settings override environment defaults. In mention mode, the current message must contain a complete, case-insensitive @agent or @<agent-handle>. Links, email addresses, previous messages, and older batched fragments do not count. Unmentioned group messages and reactions are persisted as background context for the next waking turn, without model calls, tools, typing, or interrupting work. Ordinary local slash controls and native /approve <id> <decision> answers from the prompted sender remain available without a mention. Eligible ordinary messages reach OpenClaw immediately and follow its native queue/steering settings; the plugin does not replace that scheduler or force an abort-and-restart on every new message. Quiet messages never enter that queue. Companion model turns are processed serially within their conversation scope.

Automatic SMS/iMessage groups allow the model to remain silent during ordinary chatter. The dispatch uses OpenClaw's Inkbox-only surfaces.inkbox.silentReply.group="allow" default without changing saved config; explicit surface or agent-default silence settings are preserved. Current mentions and commands retain the host's required-reply behavior. On newer OpenClaw hosts, ordinary direct requests require an answer: NO_REPLY alone does not suppress it. Successful explicit completeSilently sends still suppress duplicate acknowledgements.

Companion mode is enabled separately on the Inkbox identity by an administrator who selects a sponsor. Installing this plugin does not change that configuration. Sponsored email, group MMS, and supported dedicated-line iMessage conversations load the complete authorized initialization snapshot through the SDK, including later pages, notices, and attachment references. Environment, identity, channel, conversation scope, and activation isolate sessions. An activation is an access period, not an individual message; ordinary tracked messages remain separate.

Safe mode wakes only for current messages with sender_access: "direct". Sponsored messages and messages with missing or unknown access stay context-only. Relaxed mode may respond to any delivered sender. Admission metadata is not a statement of trust or permission to execute commands. In Companion email mention mode, the agent's actual mailbox in the current To list also counts as addressed; Cc-only messages do not. This never bypasses Safe mode.

Companion slash controls require the current access/addressing gates and the sponsor. Eligible controls can reach a running turn without waiting for its model reply. /clear uses OpenClaw's /new, /cancel uses /stop, and /health shows native session /status. OpenClaw has no historical-session picker for /resume; the channel explains that limitation without starting a model or claiming a session was resumed. Native /approve <id> <decision> answers require those same access/addressing gates and the original waking turn's sender, who may differ from the sponsor in Relaxed mode (email matching is case-insensitive). In mention mode, use, for example, @agent /approve <id> allow-once. Native approval prompts are delivered immediately on the original turn's route; eligible answers resolve the waiting host approval without starting another model turn. Pending prompts expire or clear with the host's approval lifecycle. History never acts as a new command or approval. Later replies use the saved sponsor message for email or the canonical group conversation for texts; they do not reload activation history before every turn or send.

Inputs are bounded at 128 KiB and are not silently truncated. Private journals in ~/.openclaw/inkbox/ persist receipts before acknowledgment and background context across restarts. Completed model replies are checkpointed before sending. Known transient pre-submission/pre-send failures retry with bounded backoff. Other preparation failures stop after five retries; uncertain host submissions or sends remain paused for inspection, never blindly replayed. This is at-least-once webhook delivery, not a guarantee of exactly-once model execution. Ordinary mention-mode background context retains compact sender/text/media entries up to 128 KiB; when older context is omitted, the next waking turn receives an explicit retention notice. Status/stop/approval commands do not consume background context; an authorized, committed reset clears the captured context even if its acknowledgment cannot be delivered. Companion snapshots remain fail-closed at their size limit and are never silently truncated.

Bundled Skills

The package includes all skills/*/SKILL.md files in npm tarballs.

Skill Trigger
inkbox-troubleshooting Runtime/config errors, failed tools, readiness issues
inkbox-email-triage Checking or replying to Inkbox email
inkbox-sms-responder Sending, replying to, or triaging SMS
inkbox-imessage-responder Sending, replying to, or triaging iMessage
inkbox-outbound-calling Placing calls to numbers or contacts
inkbox-call-review Reviewing calls and transcripts
inkbox-contact-lookup Resolving, creating, or updating contacts
inkbox-contact-rules Managing mail/phone allow and block rules
inkbox-identity-access Granting/revoking contact or note visibility
inkbox-notes-memory Saving, retrieving, or updating Inkbox notes
inkbox-credential-use Fetching vault credentials or TOTP codes
inkbox-outreach-sequence Multi-step outreach over email/SMS

Development Commands

npm run typecheck
npm test
npm run build
npm_config_cache=/tmp/npm-cache npm pack --dry-run

Architecture Notes

  • Plugin, not fork: uses OpenClaw plugin SDK, channel gateway, tools, HTTP routes, CLI, and bundled skills.
  • Agent-scoped: runtime should use an Inkbox agent-scoped API key.
  • Tunnel-first inbound: with a signing key, gateway opens an Inkbox tunnel, creates mail/text webhook subscriptions (plus an identity-owned iMessage subscription when enabled), and wires the incoming-call URL.
  • Voice: Inkbox STT/TTS fallback path and realtime raw-media path both route through the same call WebSocket.
  • Post-call actions: realtime calls can register, edit, delete, and dispatch work for the main OpenClaw agent after hangup.
  • Hangup: realtime calls expose a two-step hangup tool so the agent can say goodbye before dropping the phone leg.
  • Identity-aware calls: call prompts include agent handle/mailbox/phone/tunnel and known caller contact metadata.

See PLAN.md for the longer architecture history and roadmap.

License

MIT - see LICENSE.

About

Inkbox plugin for OpenClaw — adds email, SMS, and voice messaging tools and inbound webhook handling

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages