Import ADK Threads

Import historical Google ADK sessions into Enterprise Intelligence as persistent CopilotKit threads.


What is this?#

The ADK importer reads already-persisted Google ADK sessions and writes them into Enterprise Intelligence as CopilotKit threads. It supports ADK database session stores and Vertex/Agent Engine session history.

Import is a one-time migration for existing sessions. Run it from a CopilotKit app created with the CLI and Enterprise Intelligence enabled.

Prerequisites#

  • A CopilotKit app created with the CLI and Enterprise Intelligence enabled.
  • Persisted ADK sessions. In-memory ADK sessions cannot be exported.
  • ADK source credentials in environment variables.
  • An agent map from ADK app_name values to your live CopilotKit agentIds.

Legacy ADK pickle stores

Legacy ADK pickle stores are not parsed by the importer. Migrate those sessions with ADK's session migration command first, then re-run the import against the migrated store.

Select the target project#

The importer uses the Enterprise Intelligence project selected when you created the app with the CopilotKit CLI. If that is the project that should receive the ADK sessions, continue to source configuration.

To target a different cloud-hosted project, select it before the dry run:

Terminal
npx copilotkit@latest project select

The command updates the project selected for the current directory and provisions its project-scoped runtime key.

Configure the source#

Choose the ADK backend to read from.

Terminal
export ADK_SOURCE_BACKEND="database"
export ADK_DATABASE_CONNECTION_STRING="postgres://..."
export ADK_IMPORT_SCOPES="support:user-123"

ADK_IMPORT_SCOPES accepts comma-separated selectors such as app:user, app:*, *:user, or *.

Terminal
export ADK_SOURCE_BACKEND="vertex"
export ADK_VERTEX_PROJECT_ID="my-gcp-project"
export ADK_VERTEX_LOCATION="us-central1"
export ADK_VERTEX_AGENT_ENGINE_ID="..."
export ADK_IMPORT_SCOPES="support:*"

The importer uses your Google application default credentials or service account credentials in the same way ADK does.

You can also pass the backend and scopes as CLI flags:

Terminal
npx copilotkit@latest import \
  --source adk \
  --adk-source-backend database \
  --adk-import-scopes "support:user-123" \
  --dry-run

Run a dry run#

Preview the import before writing anything.

Terminal
npx copilotkit@latest import --source adk --dry-run

The dry run discovers ADK app names, counts sessions, reports sessions that cannot be imported, and estimates upload size.

Map ADK app names to CopilotKit agent IDs#

The source agent key for ADK is app_name. Map each discovered app name to the agentId your live CopilotKit runtime uses.

agent-map.json
{
  "support": "support-agent",
  "research": "research-agent"
}

Using the same agentId as live traffic keeps imported sessions and future conversations grouped together.

Import the sessions#

Run the import after the dry run and agent map look right.

Terminal
npx copilotkit@latest import \
  --source adk \
  --agent-map ./agent-map.json

For self-hosted Enterprise Intelligence, pass the target connection explicitly:

Terminal
npx copilotkit@latest import \
  --source adk \
  --api-url "$INTELLIGENCE_API_URL" \
  --api-key "$INTELLIGENCE_API_KEY" \
  --agent-map ./agent-map.json \
  --yes

ADK user attribution defaults to session.user_id. Sessions without a recoverable user are omitted by default; use --unrecoverable imported-unknown only when you intentionally want to place those sessions under an imported fallback user.

Re-run or replace#

Re-running the same import is idempotent. Sessions already imported from the same source are skipped.

Use --replace to delete and re-import previously imported sessions:

Terminal
npx copilotkit@latest import \
  --source adk \
  --agent-map ./agent-map.json \
  --replace

Keep future ADK conversations synced#

Historical import does not keep polling ADK. Your CLI-created app already sends new CopilotKit conversations to the selected Enterprise Intelligence project. To keep each conversation continuous, reopen it with the same CopilotKit threadId using one of these UI paths:

  • Threads Drawer: follow the Threads Drawer guide. The drawer and chat share a CopilotChatConfigurationProvider, so selecting a conversation updates the active threadId without separate state wiring.
  • Headless Threads: follow the Headless Threads guide. Select a thread with useThreads, store its thread.id, and pass that value to your chat component as threadId.

If your ADK backend maps CopilotKit thread IDs to ADK session IDs, keep that mapping stable so a resumed CopilotKit thread reaches the expected ADK session.