@adcp/sdk API Reference - v14.3.0
    Preparing search index...

    Class InMemoryImplicitAccountStore<TCtxMeta>

    In-memory AccountStore for resolution: 'implicit' platforms.

    Wire contract:

    1. Buyer calls sync_accounts → framework calls upsert() → store records authKey → accounts[].
    2. Buyer calls any tool (e.g. create_media_buy) without ext.account_ref → framework calls resolve(undefined, ctx) → store looks up by authKey.
    3. If no prior sync: resolve() returns null → framework emits ACCOUNT_REQUIRED. Do NOT return AUTH_REQUIRED — that signals missing credentials, not a missing pre-sync.

    This class is intentionally minimal. Copy-and-adapt for durable stores (Postgres, Redis); see docs/guides/account-resolution.md for the DDL reference and the key-derivation rationale.

    import { InMemoryImplicitAccountStore } from '@adcp/sdk/server';

    const accountStore = new InMemoryImplicitAccountStore({
    buildAccount: async (ref, ctx) => {
    const upstream = await myPlatform.findOrCreate(ref, ctx?.authInfo);
    return {
    id: upstream.id,
    name: upstream.name,
    status: 'active',
    ctx_metadata: { upstreamId: upstream.id },
    };
    },
    });

    // Wire into createAdcpServer:
    createAdcpServer({ accounts: accountStore, ... });

    Type Parameters

    • TCtxMeta = Record<string, unknown>

    Implements

    Index
    resolution: "implicit" = ...

    How buyers reference accounts on this platform. Three onboarding models, aligned with the account-reference taxonomy clarified upstream in adcp#5062:

    Mode Roster owner Discovery Durable wire reference
    'explicit' (default) Seller (you) none required — IDs issued out-of-band, or list_accounts when you wire it { account_id } or the { brand, operator } natural key
    'implicit' Buyer-declared sync_accounts { brand, operator } natural key
    'derived' Upstream platform you front list_accounts (required) { account_id }
    • 'explicit' — a seller-owned account-id namespace. You issue the ids (Snap, Meta, GAM via Network/Company id, a publisher storefront table). The framework applies no reference-shape constraint: both union arms reach accounts.resolve.
    • 'implicit' — buyer-declared accounts. The buyer must sync_accounts first; subsequent requests resolve from the auth principal's pre-synced linkage (LinkedIn, some retail-media operators). Framework refuses inline account_id references for these platforms — emits AdcpError('INVALID_REQUEST', { field: 'account.account_id' }) before reaching accounts.resolve. The brand+operator union arm is permitted (it is the durable key for this mode); only account_id-shaped references are rejected.
    • 'derived' — an upstream-managed account-id namespace. The agent fronts a platform that owns its own roster (Meta / Snap business accounts, AudioStack workspaces, a retail-media proxy). Roster size is an operational property of the upstream, not a different SDK pattern: N=1 and N=many adopters share one wire contract. The buyer calls list_accounts to discover ids, then passes { account_id } on every account-scoped request. Framework refuses the brand+operator arm for these platforms — AdcpError('INVALID_REQUEST', { field: 'account.brand' }) with a list_accounts suggestion — because the natural key is not a durable reference into someone else's namespace. accounts.list is required (createAdcpServerFromPlatform throws PlatformConfigError without it); accounts.resolve MUST verify that a buyer-supplied account_id is one the caller's credential can actually reach. createDerivedAccountStore does both for you.

    Changed in SDK 14 (breaking, adcp-client#1647). 'derived' used to be documented as "single-tenant; no account_id on the wire" and the framework refused inline account_id for it. That was inverted: it made the mode unusable for the upstream-managed adopters it exists for, and left buyers who called list_accounts with ids that every subsequent call rejected. Agents that genuinely have no discoverable namespace and hand out ids out-of-band belong in 'explicit'.

    The mode keeps the name 'derived' even though the spec calls the shape an upstream-managed account-id namespace — see AccountResolutionMode for why no alias is offered.

    Defaults to 'explicit' when omitted.

    • Resolve the caller's account from the auth-principal→account mapping populated by a prior sync_accounts call.

      Returns null (→ ACCOUNT_REQUIRED on an account-required operation whose request omitted account) when:

      • No prior sync_accounts was called for this principal
      • The stored entry has exceeded ttlMs
      • ctx.authInfo is absent or carries no extractable key

      Supplied references match the complete stored natural key. An omitted reference retains the historical first-account selection.

      Parameters

      Returns Promise<Account<TCtxMeta> | null>

    • Process a sync_accounts payload: build accounts from refs and store them under the caller's auth key.

      The auth key is extracted from ctx.authInfo via keyFn. When the key cannot be derived (no credential or unrecognized credential kind), all refs are returned as SYNC_FAILED rows — a silent-success-then- mystery-failure sequence is worse than an explicit error. Check your authenticate callback and keyFn if you see this error.

      When ctx.authInfo is absent (unauthenticated call), all refs fail with UNAUTHENTICATED. Your authenticate callback in serve({ authenticate }) should reject unauthenticated requests before reaching this method.

      Parameters

      Returns Promise<SyncAccountsResultRow[]>

    • Return the auth key that would be derived from authInfo. Useful in tests to assert that a specific principal's linkage was stored.

      Parameters

      • authInfo: ResolvedAuthInfo

      Returns string | undefined