Workflow messages wake mentioned agents but are dropped by the harness author gate (owner-only/allowlist)
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
A workflow `send_message` step that mentions agents (`@Name`) wakes them —
but agents configured `respond_to: owner-only` (the common default) never act
on the message. The agent wakes, replays the mention, silently drops it, and
goes back to sleep. No error is surfaced anywhere (the drop is a `debug!`).
## Mechanism
Workflow messages are **relay-signed** with owner attribution by convention:
`workflow_sink.rs` signs with `state.relay_keypair` and puts the owner in the
first `p` tag; the relay's own `effective_message_author()`
(`handlers/ingest.rs`) resolves "if signer == relay, real author is the
`actor`/first-`p` tag" and honors it across deletion auth, counters, workflow
ownership, etc.
`buzz-acp` never implements this convention. Its inbound author gate
(`lib.rs`, `author_allowed`) uses the raw signer:
```rust
let author = buzz_event.event.pubkey.to_hex(); // the RELAY's key
```
So for `owner-only` (and `allowlist`) agents, the relay's pubkey is neither
the owner nor a sibling and the event is dropped — *after* the wake path
(p-tag gated, `event_mentions_agent`) has already fired. The two gates
disagree about what a workflow message is.
## Why the harness can't easily fix it alone
Honoring `actor`/first-`p` attribution is only safe when the signer is
verifiably the relay — otherwise any member can forge an attribution tag and
impersonate the owner past an `owner-only` gate. The harness has no
trustworthy way to learn the relay's signing key today: the relay's NIP-11
document publishes `pubkey: null`.
## Suggested fix
1. Publish the relay's signing pubkey (NIP-11 `pubkey`, and/or inject it into
the harness env at launch, e.g. `BUZZ_RELAY_PUBKEY`, the way identity env
vars already flow).
2. In `buzz-acp`'s author gate, when `event.pubkey == relay_pubkey`, resolve
the effective author via the same `actor`/first-`p` convention as
`effective_message_author()` and gate on that.
3. Consider having the relay reject client-submitted events that carry an
`actor` tag, so attribution stays relay-only by construction.
4. Upgrade the gate-drop log from `debug!` to something owner-visible — a
woken-and-silent agent is otherwise indistinguishable from a dead one.
## Repro
1. Agent with `respond_to: owner-only`, member of a channel.
2. Workflow in that channel with a `send_message` step whose text mentions
the agent (`@AgentName`), owned by the agent's owner.
3. Trigger the workflow. The message posts, renders as the owner, carries the
agent's `p` tag; a sleeping remote agent wakes.
4. The agent never responds. Harness log (debug level): `inbound author gate —
dropping event` with the relay's pubkey as author.
## Workaround
Switch the agent to `respond_to: allowlist` and add the relay's signing
pubkey to the allowlist (obtainable from any workflow message's `pubkey`
field). Note this widens access: any member's workflow mentioning the agent
can then prompt it.
Related: #7065 (found while diagnosing the same workflow — the scheduler issue is why the workflow was being triggered manually in the first place).
Contributor guide
Research direction
Read lib.rs and trace author_allowed from the inbound wake path, then compare its raw signer handling with workflow_sink.rs and effective_message_author() in handlers/ingest.rs. Reproduce the owner-only workflow case described in the issue; done means relay attribution is accepted only for a trusted relay, forged actor attribution remains rejected, and gate drops are visible to owners.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authorization, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100