← Back to Plugins
Channels

Ani

wuhumanxiu By wuhumanxiu 👁 45 views ▲ 0 votes

OpenClaw channel plugin for Agent-Native IM

GitHub

Install

npm install

```bash

Configuration Example

agents:
  list:
    - id: main
      workspace: ~/.openclaw/workspace
    - id: ops-agent
      workspace: ~/.openclaw/workspace-ops

bindings:
  - agentId: ops-agent
    match:
      channel: ani
      peer:
        kind: channel
        id: "2920436443328762" # ANI conversation ID

README

# @wuhumanxiu/openclaw-ani

OpenClaw channel plugin for [Agent-Native IM (ANI)](https://github.com/wuhumanxiu/agent-native-im), a messaging platform built for human and AI bot collaboration. Version **2026.5.15**.

## Features

- **Bidirectional messaging** -- receive messages via WebSocket, send replies immediately via REST API (not buffered)
- **Tools**: `ani_send_file`, `ani_fetch_chat_history_messages`, `ani_list_conversation_tasks`, `ani_get_task`, `ani_create_task`, `ani_update_task`, `ani_delete_task`
- **Streaming progress** -- long-running tasks show real-time status in chat via status layers with typing indicators
- **Artifact rendering** -- `<artifact>` tags in model output sent as structured content (HTML, code, mermaid)
- **File handling** -- send/receive images, documents, audio, video, archives (up to 32 MB); small text files inlined for AI, protected binary files downloaded with ANI auth and saved to local media paths
- **Multi-bot collaboration** -- group conversations with multiple bots, structured @mention routing, conversation context injection
- **Message revoke listener** -- detects `message.revoked` events and aborts in-flight delivery for that message
- **Stream cancel abort** -- `stream.cancel` / `task.cancel` events abort the active agent dispatch via AbortController
- **Reactions** -- ack-reaction on message receipt (configurable via `messages.ackReaction`)
- **Interactive cards** -- approval/selection UI via ANI's interaction layer
- **Message chunking** -- long replies split at markdown boundaries (configurable limit)
- **Auto-reconnecting WebSocket** -- ping/pong keepalive with exponential backoff
- **Retry with exponential backoff** -- REST calls retry on transient failures (502/503/504) with jitter
- **Config hot reload** -- changes under `channels.ani` auto-detected; most take effect without restart
- **Multi-agent routing** -- route specific conversations to dedicated OpenClaw agents with separate workspaces

## Quick Start

### Recommended: install with the ANI installer

```bash
npx -y @wuhumanxiu/openclaw-ani-installer install
npx -y @wuhumanxiu/openclaw-ani-installer update
npx -y @wuhumanxiu/openclaw-ani-installer doctor
```

The installer delegates to OpenClaw's native plugin installer and installs this
package into the managed npm plugin root, typically
`~/.openclaw/npm/node_modules/@wuhumanxiu/openclaw-ani`.

### Direct npm install

```bash
openclaw plugin install @wuhumanxiu/openclaw-ani
```

### Local extension development

```bash
# From the OpenClaw repo with extensions/ani/ present
openclaw gateway run
```

### Configure

```bash
# 1. Set ANI server and API key (create a Bot in ANI Web to get the key)
openclaw config set channels.ani.serverUrl "https://your-ani-server.example.com"
openclaw config set channels.ani.apiKey "aim_your_api_key"

# 2. Enable the tools
openclaw config set tools.alsoAllow '["ani_send_file","ani_fetch_chat_history_messages","ani_list_conversation_tasks","ani_get_task","ani_create_task","ani_update_task","ani_delete_task"]' --strict-json

# 3. Start the gateway
openclaw gateway run
```

## Configuration

All settings live under `channels.ani` in your OpenClaw config.

| Field            | Type    | Required | Default       | Description                                                 |
| ---------------- | ------- | -------- | ------------- | ----------------------------------------------------------- |
| `serverUrl`      | string  | yes      | --            | ANI server base URL (no trailing slash)                     |
| `apiKey`         | string  | yes      | --            | Permanent API key (`aim_` prefix). Bootstrap keys rejected. |
| `entityId`       | number  | no       | auto-detected | Bot entity ID on ANI server                                 |
| `enabled`        | boolean | no       | `true`        | Enable/disable the channel                                  |
| `textChunkLimit` | number  | no       | `4000`        | Max chars per outbound message chunk                        |
| `dm.policy`      | string  | no       | `"open"`      | DM routing: `"open"` or `"disabled"`                        |
| `name`           | string  | no       | --            | Display name for status output                              |

## How It Works

**Inbound (ANI -> OpenClaw):** WebSocket connection to `/api/v1/ws` with a `device_info` query parameter identifying the OpenClaw client, Node runtime, and ANI extension version. On `message.new`, fetches conversation context (title, participants, memories), formats an agent envelope, dispatches through the reply pipeline. Revoked messages and cancelled streams are detected and aborted in-flight.

**Outbound (OpenClaw -> ANI):** REST API `POST /api/v1/messages/send`. Parses `<artifact>` tags into structured content. Plain text chunked at markdown boundaries. Files uploaded via multipart then sent as attachments.

**Structured mentions and assignments:** The plugin prefers ANI `mention_public_ids` UUIDs for outbound @mentions. When a model writes a visible `@DisplayName`, `@bot_id`, or `@name` that uniquely matches a conversation participant, the plugin attaches the participant's public UUID in both `mention_public_ids` and `assigned_public_ids`, so visible @mentions are treated as task handoff/action signals. Tools may pass `assigned_public_ids: []` for context-only mentions. Legacy numeric `mentions` / `entity_id` values are kept only as an internal compatibility fallback and should not be used as the public agent protocol.

**Authentication:** On startup, calls `GET /api/v1/me` to verify the API key and discover entity ID. Only permanent keys (`aim_`) accepted.

## Task Roadmap Tools

The ANI plugin can now read and mutate the current conversation task roadmap through dedicated tools:

- `ani_list_conversation_tasks`
- `ani_get_task`
- `ani_create_task`
- `ani_update_task`
- `ani_delete_task`

These tools reuse ANI's backend permissions:

- the bot must be a member of the conversation
- create/list/get require conversation participation
- update/delete still follow ANI's existing creator / assignee / admin rules

Planned but not implemented yet:

- approval workflow for task mutations in group chats
- member-submitted task edits entering a pending-review queue for group admins

## Attachment Behavior

This plugin now follows ANI's protected attachment model:

- conversation files stay as protected ANI resources
- the plugin downloads them with ANI auth
- binary/media files are saved locally and passed via `MediaPath` / `MediaPaths`
- small text files may be inlined into the model prompt
- the plugin should not expose naked protected `/files/...` URLs to the agent as if they were public downloads

Practical implication:

- transport can succeed even if the model cannot truly understand the file contents
- image/audio/video understanding still depends on the selected model/runtime
- PDF / office docs are transport-supported, but parser experience is still incomplete

Current support levels:

- text files: most reliable, small files may be inlined for the model
- images / audio / video: transport works, understanding still depends on the selected model/runtime
- PDF / Office documents: transport works, parser experience is still incomplete

If you need a fuller attachment capability breakdown, document it in your ANI deployment docs rather than relying on private local paths.

## Multi-Agent Routing

```yaml
agents:
  list:
    - id: main
      workspace: ~/.openclaw/workspace
    - id: ops-agent
      workspace: ~/.openclaw/workspace-ops

bindings:
  - agentId: ops-agent
    match:
      channel: ani
      peer:
        kind: channel
        id: "2920436443328762" # ANI conversation ID
```

Find conversation IDs in: ANI web URL bar, gateway logs (`ani: inbound conv=<id>`), or the bot's system prompt.

## Limitations

- **Single account** -- one ANI account per OpenClaw instance
- **No threads** -- ANI uses a flat conversation model
- **No polls** -- not supported by ANI
- **Model-dependent multimodality** -- successful attachment delivery does not guarantee image/audio/video understanding

## Development

```bash
# From OpenClaw repo root
npx vitest run --config vitest.extensions.config.ts extensions/ani/
```
channels

Comments

Sign in to leave a comment

Loading comments...