Tools
Intent Context
OpenClaw plugin for passive cross-agent awareness and mechanical notify intent execution
Install
npm install
npm
Configuration Example
{
"config": {
"intentsDir": "~/.openclaw/intents",
"agents": {
"pax": {
"actorFor": ["pax"],
"ambientScope": ["scout", "roger", "pax"]
},
"scout": {
"watchedTriggerTypes": ["home_event", "device_presence"]
}
},
"notifyExecutorIntervalMs": 60000,
"recentActivityWindowMs": 86400000,
"logRetentionMs": 172800000,
"openclawBin": "/opt/homebrew/bin/openclaw",
"fallbackNotifyChannel": "bluebubbles"
}
}
README
# OpenClaw Intent Context Plugin
The Intent Context plugin gives OpenClaw agents passive awareness of each other and mechanically executes notification-type triggered intents. It injects relevant pending intents and recent cross-agent activity into each agent's turn as it happens, so agents can act on what's going on across the system without being explicitly told. It also runs a background timer that delivers `notify`-type triggered intents via `openclaw message send`, so deterministic notifications fire without burning an LLM turn. No agent is ever actively woken — everything surfaces on whatever turn happens next.
Without this plugin, OpenClaw agents operate in isolation. They have no visibility into what other agents are doing, what intents are pending in the system, or what events have recently occurred outside their own session. Multi-agent coordination requires manual messaging or cron jobs. Notifications that should fire automatically when an intent is triggered either need a full LLM-backed agent turn every poll cycle (expensive and slow) or don't happen at all. External systems like home automation pipelines, transaction monitors, or email processors have no way to surface events to agents — they'd need to actively wake an agent or send a message, which is heavy, intrusive, and doesn't scale across multiple agents. Cross-agent awareness, automated notification delivery, and external event ingestion are all left unsolved.
The plugin solves these problems through passive context injection and a mechanical notify executor. A `before_prompt_build` hook reads pending intents and recent activity from shared log files and injects them into whichever agent turn is already happening — so agents see what's pending, what's been triggered and assigned to them, and what other agents have been doing, all without any active wake. The `log_activity` tool lets any agent or external system append to the activity log via a simple HTTP call, so home automation pipelines, transaction monitors, and other services can surface events the same way agents do. A `gateway_start` timer mechanically executes `notify`-type triggered intents by rendering the message template and sending it via `openclaw message send` — no LLM turn needed, no agent judgment required, just deterministic delivery on a timer.
## The `log_activity` Tool
The plugin registers a `log_activity` tool that any agent or external system can use to append to the shared ambient-activity log:
```
log_activity(text: string, agent?: string)
```
- `text` — short description of what happened
- `agent` — optional identifier for external systems (defaults to the calling agent's id)
External systems can call it via the Gateway's `/tools/invoke` HTTP endpoint:
```bash
curl -sS http://127.0.0.1:18789/tools/invoke \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"tool":"log_activity","args":{"text":"Driveway: vehicle arrived","agent":"marlin"}}'
```
The entry is appended to `~/.openclaw/intents/recent-activity.jsonl` and surfaces in configured agents' next turn under `RECENT ACTIVITY`.
## Architecture
**Passive injection, never active wake.** The plugin reads local files and injects context into turns that are already happening. It never triggers a new turn.
**Data sources** (all under `~/.openclaw/intents/`):
| File | Written by | Surfaces as |
|------|-----------|-------------|
| `pending.json` | intent system | `WATCHING FOR` + `ACTION NEEDED` |
| `recent-activity.jsonl` | `log_activity` tool | `RECENT ACTIVITY` |
**Per-agent filtering** is entirely read-time, from `config.agents[agentId]`:
- `watchedTriggerTypes` — pending intents where `status="pending"` and `trigger.type` matches
- `actorFor` — pending intents where `status="triggered"` and `notify_agent` matches
- `ambientScope` — `"all"` or a list of agent ids to see activity from
If an agent has no entry in `config.agents`, the hook returns early and injects nothing.
**Notify executor** (`gateway_start` timer, default 60s): scans `pending.json` and `archive.json` for `status="triggered"` + `action.type="notify"`, renders `action.message_template` against `trigger_data` (`{{key}}` substitution, missing → `"N/A"`), shells out to `openclaw message send`, then sets `status="completed"` in place. `agent_task`-type intents are deliberately left alone — those need judgment and surface via injection instead.
Concurrency is guarded by a `mkdir`-based lock at `~/.openclaw/intents/.lock` with stale detection and automatic reclaim.
## Build
```bash
npm install
npm test
npm run plugin:build
```
`npm run plugin:build` runs `tsc` only (no bundler step).
### What does NOT work
- `openclaw plugins build --entry …` and `openclaw plugins validate --entry …` do not work for this plugin. Do not use them.
- `openclaw.plugin.json` is **hand-authored** — it is not generated by a build step. Edit it directly if you change the config schema or tool parameters.
- There is no `plugin:validate` script.
## Configuration
Add to `~/.openclaw/openclaw.json` under `plugins.entries.intent-context`:
```json
{
"config": {
"intentsDir": "~/.openclaw/intents",
"agents": {
"pax": {
"actorFor": ["pax"],
"ambientScope": ["scout", "roger", "pax"]
},
"scout": {
"watchedTriggerTypes": ["home_event", "device_presence"]
}
},
"notifyExecutorIntervalMs": 60000,
"recentActivityWindowMs": 86400000,
"logRetentionMs": 172800000,
"openclawBin": "/opt/homebrew/bin/openclaw",
"fallbackNotifyChannel": "bluebubbles"
}
}
```
### Config fields
| Field | Default | Description |
|-------|---------|-------------|
| `intentsDir` | `~/.openclaw/intents` | Path to the shared intents store |
| `agents` | (required) | Per-agent awareness config, keyed by agentId |
| `agents.<id>.watchedTriggerTypes` | — | Trigger types to watch for in pending intents |
| `agents.<id>.actorFor` | — | `notify_agent` values this agent acts on |
| `agents.<id>.ambientScope` | — | `"all"` or array of agent ids to see activity from |
| `notifyExecutorIntervalMs` | `60000` | Poll interval for the notify executor |
| `recentActivityWindowMs` | `21600000` (6h) | How far back to surface activity entries |
| `logRetentionMs` | `172800000` (48h) | Retention for pruning the activity log |
| `openclawBin` | `/opt/homebrew/bin/openclaw` | Path to the openclaw CLI binary |
| `fallbackNotifyChannel` | `bluebubbles` | Channel used when an intent's `action.channel` is unset |
## Installation
1. Clone or copy this project to a directory
2. Run `npm install && npm run plugin:build`
3. Add to `~/.openclaw/openclaw.json` under `plugins.entries.intent-context`
4. `openclaw gateway restart` (always do a full restart — `gateway_start` does not fire on hot-reload)
## After Any Change
A full `openclaw gateway restart` is required for the plugin to reload. There is no hot-reload.
## License
MIT
tools
Comments
Sign in to leave a comment