Skip to content

Conversation store: owner-based session creation (session_owner) isn't in the WP_Agent_Conversation_Store interface #325

@lezama

Description

@lezama

Summary

The canonical agents/chat input schema promotes a session_owner concept for transcripts that aren't owned by a logged-in user — agents_chat_session_owner_schema() documents it as:

Opaque, isolating owner for persisted conversation sessions. Use for anonymous browser or external-channel chats when no logged-in user owns the transcript. … such as user:<id>, browser:<opaque id>, or a channel-specific conversation key.

But the WP_Agent_Conversation_Store interface only offers a user-centric creation method:

// src/Transcripts/class-wp-agent-conversation-store.php:63
public function create_session( WP_Agent_Workspace_Scope $workspace, int $user_id, string $agent_slug = '', array $metadata = array(), string $context = 'chat' ): string;

The owner-based creation that matches session_owner exists only on the concrete CPT implementation, not in the interface:

// src/Transcripts/class-wp-agent-cpt-conversation-store.php:193
public function create_session_for_owner( WP_Agent_Workspace_Scope $workspace, array $owner, string $agent_slug = '', array $metadata = array(), string $context = 'chat' ): string;

Impact

A consumer coding against the contract (resolving the store via apply_filters( 'wp_agent_conversation_store', null ) and treating it as a WP_Agent_Conversation_Store) cannot portably create an anonymous / browser-owned session — the only interface method requires an int $user_id. To use the very session_owner vocabulary the chat schema defines, you have to either bind to the concrete WP_Agent_Cpt_Conversation_Store (defeating the interface) or fall back to user_id = 0, which conflates "guest" with "no owner."

Concretely: an anonymous public chat surface (e.g. a served site, a support widget) has no user_id, and session_owner: { type: "browser", key: "<opaque>" } is exactly the intended model — but it's unreachable through the contract.

Proposal

Promote owner-based creation to the WP_Agent_Conversation_Store interface so the contract matches the canonical session_owner vocabulary. Either:

  • add create_session_for_owner( WP_Agent_Workspace_Scope $workspace, array $owner, … ): string to the interface, or
  • make create_session accept an owner (e.g. int|array $user_or_owner, or an optional ?array $owner that supersedes $user_id).

The CPT store already implements it; this is mostly about lifting it into the contract (+ a default/adapter for stores that only know user_id).

Secondary observation

The agents/chat dispatcher (src/Channels/register-agents-chat-ability.php) doesn't write to the registered conversation store — persistence is entirely consumer-wired. That may be intentional (consumers own materialization policy), but it's worth a doc note, since both the store and the canonical session_owner shape exist and a newcomer reasonably expects the chat path to use them.

Context

Surfaced while building an example consumer (an "agent-served site" on agents-api + wp-ai-client): https://github.com/lezama/agent-served-site — its Session_Store resolves the store via the filter and uses create_session/get_session/update_session, and had to settle for user_id instead of a browser owner for anonymous visitors. Related: #324 (per-agent register_chat_handler routing).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions