You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: a gateway silence read as "not my conversation"
The gateway response carried only whether a reply came back, and the
forwarder used that to decide whether to suppress AstrBot's own model. But
this agent is quiet on purpose far more often than it speaks: a PASS, several
messages merged into one answer by the debounce, the rhythm gate. All of
those return handled=false.
So the forwarder read the persona's deliberate restraint as "not mine" and
handed the room to its built-in model, which then answered in it as someone
else. That is worse than not replying — the restraint is the behaviour being
overridden, and it is the most common outcome by design.
The response now carries `owned` beside `handled`, set once the turn clears
the admission gates, which is the moment the answer to "is this conversation
mine" is known. Everything after that point is about what to say, including
saying nothing. The plugin gates stop_event() on `owned` and falls back to
`handled` when the field is absent, so an older agent behaves exactly as it
does today — pinned by the existing unhandled-response test.
Mutation-checked: conflating the two again (the pre-change semantics) fails
the assertion that a PASS still claims the conversation, and claiming every
turn from the start fails the assertion that a refused one does not.
Also documents the second inbound path, which nothing did. docs/deploy.md
described a QQ-only deployment and never mentioned the gateway, AstrBot, or
how to configure a second platform — the interface was configurable and
undiscoverable. Includes the two AstrBot stages that run before plugin
handlers and would throttle or silently drop a busy QQ group.
|`private_whitelist`| list |`[]`| Allowed private senders; empty = none. |
56
-
|`block_default`| bool |`true`| Call `event.stop_event()` only after the agent successfully accepts ownership (`handled: true`). Transport failures, invalid responses, and `handled: false` fall back to AstrBot's normal pipeline. |
57
-
58
-
## Important: QQ / NapCat double-handling
59
-
60
-
If NapCat already feeds the agent directly through `POST /webhook/qq`, keep
61
-
`aiocqhttp` in `excluded_platforms` (it is there by default). Otherwise the
62
-
same QQ message would reach the agent twice — once from NapCat and once from
63
-
this plugin.
56
+
|`block_default`| bool |`true`| Call `event.stop_event()` once the agent claims the conversation (`owned: true`). Transport failures, invalid responses and conversations the agent turned away fall back to AstrBot's normal pipeline. |
57
+
58
+
`owned` is not `handled`. The agent stays quiet on purpose far more often
59
+
than it speaks — a PASS, several messages merged into one answer, the rhythm
60
+
gate — and all of those return `handled: false`. Gating on that would hand
61
+
the room to AstrBot's built-in model, which would then answer as someone else
62
+
in a conversation the persona had decided to sit out. An agent too old to
63
+
send `owned` falls back to `handled`, which is what it did before.
64
+
65
+
## QQ: two ways, and you must pick one
66
+
67
+
**Default — NapCat feeds the agent directly.**`aiocqhttp` stays in
68
+
`excluded_platforms`, QQ goes NapCat → `POST /webhook/qq`, and this plugin
69
+
carries everything else. Nothing to configure.
70
+
71
+
**Or route QQ through here too**, so AstrBot is the single place you configure
72
+
every platform. Remove `aiocqhttp` from `excluded_platforms`, add the QQ group
73
+
to `group_whitelist`, stop NapCat posting to `/webhook/qq`, and set
74
+
`GATEWAY_NATIVE_PLATFORMS=aiocqhttp` on the agent.
75
+
76
+
That last setting is not optional and not cosmetic. Without it the agent
77
+
namespaces forwarded ids, so every QQ conversation arrives under a new name
78
+
and the agent addresses rooms and people that do not exist — memory, history
79
+
and every learned example are keyed the old way, and the ledgers
80
+
content-address their rows over the conversation id, so it cannot be renamed
81
+
back afterwards. With it, a QQ message relayed by AstrBot lands on exactly the
82
+
keys NapCat would have produced.
83
+
84
+
Do **not** do both at once: the same message would reach the agent twice.
85
+
86
+
Two things to change on the AstrBot side before it can carry a busy QQ group,
87
+
because both run before plugin handlers: raise or disable the rate-limit stage
88
+
(30 messages / 60 s by default, and it stalls rather than drops), and review
89
+
`content_safety.internal_keywords`, which is on by default and will silently
Copy file name to clipboardExpand all lines: integrations/astrbot/astrbot_plugin_llm_persona_gateway/_conf_schema.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@
16
16
},
17
17
"excluded_platforms": {
18
18
"type": "list",
19
-
"description": "Platform adapter names that must NOT be forwarded. Keep aiocqhttp here when NapCat already feeds the agent directly, otherwise QQ messages would be handled twice.",
19
+
"description": "Platform adapter names that must NOT be forwarded. Keep aiocqhttp here when NapCat already feeds the agent directly through /webhook/qq, otherwise QQ messages would be handled twice. To make AstrBot the single inbound path for QQ as well, remove it, stop NapCat posting to /webhook/qq, and set GATEWAY_NATIVE_PLATFORMS=aiocqhttp on the agent so QQ ids stay spelled the way every store on disk already spells them.",
0 commit comments