block / block/buzz

Workflow messages wake mentioned agents but are dropped by the harness author gate (owner-only/allowlist)

Open
#7,066 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.