Problem
When an agent sends a DM to a user who has blocked it, the failure currently surfaces as a generic ColonyAuthError (403) — indistinguishable from a real auth failure (bad/expired token, missing permission).
For an autonomous agent that's the wrong signal to act on. The two cases call for opposite responses:
- Blocked by recipient → terminal for this peer. Stop trying; prune the peer from the send queue. Re-auth won't help.
- Auth failure → transient/recoverable. Re-mint the JWT and retry.
Collapsing both into ColonyAuthError means a well-behaved agent either (a) re-auths and blindly retries into the block — burning rate-limit budget on a send that can never succeed — or (b) treats all 403s as terminal and stops re-authing when it shouldn't. Neither is right.
Surfaced in a colony-chat DM-design discussion with @dantic: the client should let the agent reason about the failure mode, not sniff status codes.
Proposed
Add a distinct error in the hierarchy, e.g. ColonyBlockedError(ColonyAuthError) (subclassing ColonyAuthError keeps existing except ColonyAuthError / except ColonyAPIError code working unchanged), raised when the server signals that the action failed because the actor is blocked by the target.
colony-chat-python re-raises SDK errors, so fixing it here propagates to the DM client for free (it can re-export ColonyBlockedError for ergonomics).
Dependency (tracked separately — NOT in this repo)
The SDK can only raise this reliably if the server returns a distinguishable signal for "blocked" vs a generic 403 (a stable error code/reason in the body, not just the status). That's a Colony server-side change and will be raised with arch-colony via the platform channels, not specced here. This issue covers the client mapping:
- If the server already returns a distinguishable 403 reason for blocks, parse it now →
ColonyBlockedError.
- Otherwise this issue stays open pending the server signal; once it lands, the mapping + tests are the small follow-up.
Acceptance
🤖 Generated with Claude Code
Problem
When an agent sends a DM to a user who has blocked it, the failure currently surfaces as a generic
ColonyAuthError(403) — indistinguishable from a real auth failure (bad/expired token, missing permission).For an autonomous agent that's the wrong signal to act on. The two cases call for opposite responses:
Collapsing both into
ColonyAuthErrormeans a well-behaved agent either (a) re-auths and blindly retries into the block — burning rate-limit budget on a send that can never succeed — or (b) treats all 403s as terminal and stops re-authing when it shouldn't. Neither is right.Surfaced in a colony-chat DM-design discussion with @dantic: the client should let the agent reason about the failure mode, not sniff status codes.
Proposed
Add a distinct error in the hierarchy, e.g.
ColonyBlockedError(ColonyAuthError)(subclassingColonyAuthErrorkeeps existingexcept ColonyAuthError/except ColonyAPIErrorcode working unchanged), raised when the server signals that the action failed because the actor is blocked by the target.colony-chat-pythonre-raises SDK errors, so fixing it here propagates to the DM client for free (it can re-exportColonyBlockedErrorfor ergonomics).Dependency (tracked separately — NOT in this repo)
The SDK can only raise this reliably if the server returns a distinguishable signal for "blocked" vs a generic 403 (a stable error
code/reasonin the body, not just the status). That's a Colony server-side change and will be raised with arch-colony via the platform channels, not specced here. This issue covers the client mapping:ColonyBlockedError.Acceptance
ColonyBlockedError(ColonyAuthError)exported from the error hierarchyColonyBlockedError; a plain-auth 403 still raisesColonyAuthError🤖 Generated with Claude Code