How to Import External Conversations into ai-memory: Complete Guide with CLI Examples

Use the ai-memory-importer binary to replay any external conversation into ai-memory by preparing a JSON envelope and running the external-conversation sub-command with --apply.

The ai-memory project provides a dedicated companion tool for importing conversations from external sources like ChatGPT, Claude, or custom LLM transcripts. This guide walks through the complete import pipeline based on the actual source code implementation in akitaonrails/ai-memory.

The Import Architecture

The importer operates as a deterministic replay system. It converts external transcripts into native ai-memory hook events, which the server processes as if they were live conversation captures. This design allows imported conversations to participate fully in ai-memory's handoff and recall mechanisms.

Key design principles from the source:

  • Idempotent replay: The same import run always produces identical session IDs
  • Safe dry-run mode: Plan imports without network calls
  • Manifest verification: Every run produces an auditable JSON record

Step 1: Prepare Your Conversation JSON Envelope

The importer expects a file matching the ConversationEnvelope struct defined in companions/ai-memory-importer/src/main.rs (lines 94-108).

Required structure:

Field Type Description
project string Target project name in ai-memory
source string Identifier for the external system (e.g., "chatgpt", "claude")
session_id string Stable external identifier for this conversation
messages array Ordered list with role (system/user/assistant) and content

Example envelope file:

cat > sample.json <<'EOF'
{
  "project": "my-project",
  "source": "chatgpt",
  "session_id": "conv-12345",
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "What is the capital of France?"},
    {"role": "assistant", "content": "Paris."},
    {"role": "user", "content": "What is its population?"},
    {"role": "assistant", "content": "Approximately 2.1 million in the city proper."}
  ]
}
EOF

Step 2: Validate with Dry-Run Mode

Never import blindly. The dry-run mode invokes plan_external_conversation to validate and display the planned events without network calls.

ai-memory-importer external-conversation \
  --file sample.json \
  --workspace DRY-RUN-WS \
  --manifest-out dry-run-manifest.json

What happens during planning:

  1. Validation: Label lengths checked, secrets redacted via secret_patterns function
  2. Sanitization: Control characters stripped from messages
  3. Size enforcement: Hard limits prevent oversized payloads
  4. Stable ID generation: stable_external_session_id (lines 91-106) creates deterministic session identifier from workspace + project + source + external session ID

The output shows each PlannedHookEvent with its ingest key, URL, and JSON body.

Step 3: Execute the Real Import

Add --apply and a valid --workspace to POST events to your ai-memory server:

ai-memory-importer external-conversation \
  --file sample.json \
  --workspace production-ws \
  --apply \
  --manifest-out import-manifest.json

Runtime flow (implemented in main.rs):

  • Hook event construction (lines 298-322): planned_hook_event and build_hook_url generate fully-qualified URLs encoding event type, identifiers, and SHA-256 ingest keys
  • Event types generated: session-start, user-prompt, external.assistant-message, session-end
  • Batch delivery (post_hook_batch, lines 445-463): Single HTTP POST to /hook/batch endpoint
  • Acknowledgment handling: Server response lists accepted events; any rejection aborts the import

Successful output resembles:


import complete: replayed 5 events into production-ws/my-project as session external-a1b2c3...

Understanding the Import Manifest

Every run produces a JSON manifest (controlled by --manifest-out). The manifest structure (conversation_manifest / write_conversation_manifest, lines 266-277) contains:

  • Source file SHA-256 hash
  • Stable session ID
  • Count of planned events
  • Count of accepted events (0 in dry-run mode)
  • Error details (if import aborted)

Use manifests to:

  • Verify dry-run vs. actual import differences
  • Audit which conversations were imported when
  • Retry failed imports with identical parameters

CLI Reference: External Conversation Sub-Command

Flag Required? Default Purpose
--file <PATH> Yes Path to JSON envelope
--workspace <NAME> Yes with --apply Target workspace
--server-url <URL> No http://127.0.0.1:49374 ai-memory server address
--apply No false Actually send events; without this, dry-run only
--manifest-out <PATH> Yes with --apply Manifest output location

Security Considerations During Import

The importer applies the same protections as live capture:

  • Secret redaction: Patterns matching API keys, tokens, and passwords are masked before transmission
  • Control character stripping: Prevents injection attacks
  • Size limits: Enforced per-message and per-batch

These protections are implemented in the planning phase before any network activity occurs.

Post-Import: Using Your Conversation

Once imported, the conversation behaves like any native ai-memory session:

  • Query via standard recall commands
  • Include in handoff contexts for new sessions
  • Search via consolidated indexing

See docs/usage.md for handoff mechanics and docs/architecture.md for how imported data flows through the capture → consolidate → recall → handoff pipeline.

Summary

  • Prepare a JSON envelope with project, source, session_id, and messages array
  • Validate with dry-run mode before network operations
  • Import using --apply flag with mandatory workspace and manifest paths
  • Verify via the generated manifest showing planned vs. accepted event counts
  • Access imported conversations through normal ai-memory recall and handoff mechanisms

The ai-memory-importer binary transforms any external transcript into first-class ai-memory knowledge with full auditability and zero runtime dependencies beyond HTTP.

Frequently Asked Questions

What conversation formats can I import?

Any transcript that fits the ConversationEnvelope JSON schema. This includes ChatGPT exports, Claude conversation logs, custom LLM outputs, or synthesized training dialogues. The schema only requires role (system/user/assistant) and content per message.

Why does the same import always produce the same session ID?

The stable_external_session_id function (lines 91-106) deterministically hashes workspace, project, source, and your external session identifier. This prevents duplicate conversations in the knowledge base and enables idempotent retry of interrupted imports.

Can I import to a remote ai-memory server?

Yes. Use --server-url to target any reachable ai-memory instance. The default http://127.0.0.1:49374 assumes local development. Ensure network connectivity and authentication (if configured) before running with --apply.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →