Skip to content

Events: stamp who caused them, so the loop guards can fire - #27

Open
nishanthvonteddu wants to merge 1 commit into
theschoolofai:mainfrom
nishanthvonteddu:fix/event-actor-never-set
Open

nishanthvonteddu wants to merge 1 commit into
theschoolofai:mainfrom
nishanthvonteddu:fix/event-actor-never-set

Conversation

@nishanthvonteddu

Copy link
Copy Markdown

Both self-trigger guards read EventEnvelope.actor. No producer ever set it, so both were unreachable.

What breaks

actor defaults to None, and every guard short-circuits on empty:

if actor and actor in self.self_actors:                        # governor.admit_event
return bool(actor) and actor in subscription.ignore_actors     # engine._self_caused

I grepped the whole package: cron_event, webhook_event, gmail_pubsub_event and the channel-message route all leave it unset. So S16_SELF_ACTORS and every subscription’s ignore_actors did nothing, and the loop the README warns about — an agent answering on a channel it also watches, seeing its own reply arrive as a new event — had nothing standing in its way.

Why it survived

The guards are tested — but the tests build envelopes by hand:

outcome = await engine.process(_event(actor="s16code"), llm=...)

The mechanism was proven. The wiring never was.

The fix

Each producer stamps the field, overridable by the caller:

producer actor
channel message "{channel}:{channel_user_id}" — the sender
Gmail push "gmail:{emailAddress}" — the watched mailbox
cron tick "cron.{schedule_id}"
webhook the source

Test

test_channel_event_records_who_sent_it posts a real channel message and asserts the stored envelope names its sender. Fails before, passes after.

`EventEnvelope.actor` is read by both self-trigger guards and defaults to
None. No producer ever set it: not cron_event, not webhook_event, not
gmail_pubsub_event, and not the channel-message route.

Both guards test the field first and admit when it is empty:

    if actor and actor in self.self_actors:              # governor
    return bool(actor) and actor in subscription.ignore_actors   # engine

So `S16_SELF_ACTORS` and every subscription's `ignore_actors` were
unreachable, and the self-sustaining loop they exist to refuse -- an agent
answering on a channel it also watches -- had nothing standing in its way.

The guards have unit tests, but those build envelopes by hand with `actor=`
already set, so the mechanism was proven and the wiring never was.

Producers now stamp it: the sending identity for a channel message, the
watched mailbox for a Gmail push, the schedule for a cron tick, the source
for a webhook, each overridable by the caller.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant