Skip to content

Replace custom ContextStore with A2A-native task history #116

@jezekra1

Description

@jezekra1

Is your feature request related to a problem? Please describe.
Conversation history is currently stored in two places: once inside A2A Tasks (task.history / task.artifacts) and again in a custom ContextStore abstraction backed by the adk-server /contexts/{id}/history API. This duplication adds complexity and diverges from the A2A protocol's native support for conversation data.

The A2A SDK now provides first-class support for task listing with contextId filtering, pagination, and owner scoping — covering all current ContextStore use cases.

Describe the solution you'd like

Use A2A Tasks as the single source of truth for conversation history. This is a breaking change — no migration path, done in one step.

Current vs Proposed

Layer Current Proposed
adk-py RunContext Calls _store.store(msg) to push to ContextStore Remove store() / load_history() — history lives in TaskUpdater's task updates (already happening)
adk-py ContextStore MemoryContextStore, PlatformContextStore Remove entirely
adk-server /contexts API Full CRUD + history endpoints Keep context metadata (title, timestamps) but drop history endpoints
UI data fetching GET /contexts/{id}/historyconvertHistoryToUIMessages() Call A2A proxy ListTasks with contextId filter → flatten task.history into UI messages
UI messages provider useListContextHistory hook New useListTasks hook against A2A endpoint

Files to remove in adk-py

  • kagenti_adk/server/store/context_store.py (abstract interface)
  • kagenti_adk/server/store/memory_context_store.py
  • kagenti_adk/server/store/platform_context_store.py
  • store() / load_history() / delete_history_from_id() on RunContext

adk-server /contexts endpoints

  • Keep: context CRUD (create, list, get, update, delete) for sidebar and metadata
  • Remove: POST /contexts/{id}/history, GET /contexts/{id}/history, DELETE /contexts/{id}/history

How agent-side history access works after the change

If an agent function needs prior conversation context, it reads from task_store.list(context_id=...) or task_store.get(task_id) directly — no separate store abstraction needed.

Conversation title generation

Currently handled by ContextService.add_history_item() which detects the first user message and generates a title. Two options:

  1. Agent-side: The agent (or a background task triggered by the agent) generates a title after the first interaction and stores it in task metadata.
  2. Server-side: The A2A proxy layer detects the first task in a context and triggers title generation as a background job, storing the result in context metadata.

Conversation metadata (title, timestamps, etc.)

The /contexts table currently stores metadata like title, created_at, last_active_at. Options:

  1. Keep lightweight /contexts table — only for metadata, no history. Simplest migration path.
  2. A2A extension — store conversation-level metadata (title, etc.) on the tasks themselves via A2A task metadata fields. The first task in a context carries the conversation metadata. Eliminates the need for a separate contexts table entirely.

Option 2 is the cleaner long-term approach but requires convention around which task holds conversation metadata.

Listing conversations for the sidebar

Currently GET /contexts lists all conversations. With A2A-only approach, we'd need a distinct query on context_id from the tasks table. Keeping the lightweight /contexts endpoint is simpler and avoids an expensive distinct query.

Describe alternatives you've considered
Keep the current dual-store approach and sync them, but this adds maintenance burden and fights against A2A's direction of providing first-class task/history management.

Additional context
The A2A ListTasks method supports all needed filtering:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "ListTasks",
  "params": {
    "contextId": "context-uuid",
    "status": "TASK_STATE_WORKING",
    "pageSize": 50,
    "pageToken": "cursor-token"
  }
}

Related: #91

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions