Skip to content

Typed dispatcher rejects valid request when account is omitted on auth-resolved tools #623

@bokelley

Description

@bokelley

Problem

The library's typed dispatcher rejects requests on tools where the spec declares `account` optional — specifically when the seller resolves identity from the auth chain and the buyer doesn't send a top-level `account` ref.

Affected wire tools (3.0.6+):

  • `create_media_buy`
  • `sync_creatives`
  • `activate_signal`
  • (others sharing the AccountReference-bound request shape)

Per spec, when an adopter is in implicit-resolution mode (auth principal IS the account scope) the buyer can omit `account`. The dispatcher's pre-handler validation insists on the field being present, blocking the request before the adopter's impl can resolve from `AuthInfo`.

Workaround on the adopter side

Inject a sentinel `account: {account_id: "auth-chain"}` placeholder at the wire boundary so the validator passes; the impl ignores the placeholder and reads identity from `ResolvedIdentity`. bokelley/salesagent's `SpecDefaultsMiddleware` does this for the four tools listed above. Workable but every adopter has to ship the equivalent.

Suggested fix

Make `account` optional on the typed dispatcher when the surface declares implicit-resolution support. Concretely:

  1. `AccountStore.resolution` is `'derived' | 'implicit' | 'explicit'` — the dispatcher already has this signal at boot.
  2. For tools that accept `account` (`create_media_buy`, `sync_creatives`, `activate_signal`, etc.), skip the required-field check on `account` when the wired `AccountStore.resolution != 'explicit'`.
  3. Keep the field required for explicit-mode adopters (where `account.account_id` IS the resolution input).

This closes the gap without changing the wire schema (which already documents `account` as optional in implicit/derived mode).

Related

  • bokelley/salesagent's middleware workaround: `core/middleware/spec_defaults.py` `_AUTH_FILLED_TOOLS` set.
  • The `auth-chain` placeholder string is contained (impl reads identity from elsewhere) but is fragile — any adopter forgetting the middleware silently gets `INVALID_REQUEST` for buyers in implicit mode.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions