# Copy Session



Create independent copies of sessions with all messages, tasks, and configurations intact. Perfect for experimentation, checkpointing, and branching workflows.

Use Cases [#use-cases]

* **Experimentation**: Try different approaches without affecting the original conversation
* **Checkpointing**: Save progress at key decision points
* **Branching workflows**: Explore parallel conversation paths from a common starting point
* **Template sessions**: Reuse successful session patterns

Basic Usage [#basic-usage]

<CodeGroup>
  ```python title="Python"
  from acontext import AcontextClient
  import os

  client = AcontextClient(api_key=os.getenv("ACONTEXT_API_KEY"))

  # Copy a session
  result = client.sessions.copy(session_id="session-uuid")

  print(f"Original session: {result.old_session_id}")
  print(f"Copied session: {result.new_session_id}")

  # Now you can modify the copied session independently
  client.sessions.store_message(
      session_id=result.new_session_id,
      blob={"role": "user", "content": "Let's try a different approach"},
      format="openai"
  )
  ```

  ```typescript title="TypeScript"
  import { AcontextClient } from '@acontext/acontext';

  const client = new AcontextClient({
      apiKey: process.env.ACONTEXT_API_KEY,
  });

  // Copy a session
  const result = await client.sessions.copy("session-uuid");

  console.log(`Original session: ${result.oldSessionId}`);
  console.log(`Copied session: ${result.newSessionId}`);

  // Now you can modify the copied session independently
  await client.sessions.storeMessage(
      result.newSessionId,
      { role: "user", content: "Let's try a different approach" },
      { format: "openai" }
  );
  ```
</CodeGroup>

Async Usage [#async-usage]

<CodeGroup>
  ```python title="Python (Async)"
  from acontext import AsyncAcontextClient
  import os
  import asyncio

  async def copy_example():
      async with AsyncAcontextClient(api_key=os.getenv("ACONTEXT_API_KEY")) as client:
          result = await client.sessions.copy(session_id="session-uuid")
          print(f"Copied session: {result.new_session_id}")

  asyncio.run(copy_example())
  ```

  ```typescript title="TypeScript"
  import { AcontextClient } from '@acontext/acontext';

  const client = new AcontextClient({
      apiKey: process.env.ACONTEXT_API_KEY,
  });

  const result = await client.sessions.copy("session-uuid");
  console.log(`Copied session: ${result.newSessionId}`);
  ```
</CodeGroup>

What Gets Copied [#what-gets-copied]

When you copy a session, the following are duplicated:

* **Messages**: All messages with preserved parent-child relationships
* **Tasks**: All tasks with their order, status, and data
* **Configurations**: Session configs and settings
* **User association**: The copied session belongs to the same project

What Doesn't Get Copied [#what-doesnt-get-copied]

* **Asset files**: S3 assets are shared (not duplicated) between sessions for efficiency
* **Message processing status**: Copied messages are marked as "pending" for reprocessing
* **Task-message links**: These are cleared and will be reassigned by the core service

Independence [#independence]

The copied session is completely independent:

* Changes to the original session don't affect the copy
* Changes to the copy don't affect the original
* Each session can have different messages, tasks, and configs going forward

Limitations [#limitations]

Size Limit [#size-limit]

Sessions with more than **5,000 messages** cannot be copied synchronously. You'll receive an error:

```json
{
  "error": "SESSION_TOO_LARGE",
  "message": "Session exceeds maximum copyable size (5000 messages). Consider using async copy."
}
```

For large sessions, async copy support is planned for a future release.

Error Handling [#error-handling]

<CodeGroup>
  ```python title="Python"
  from acontext import AcontextClient
  from acontext.exceptions import AcontextError

  client = AcontextClient(api_key="...")

  try:
      result = client.sessions.copy(session_id="invalid-uuid")
  except AcontextError as e:
      if "SESSION_NOT_FOUND" in str(e):
          print("Session does not exist or you don't have access")
      elif "SESSION_TOO_LARGE" in str(e):
          print("Session is too large to copy synchronously")
      else:
          print(f"Copy failed: {e}")
  ```

  ```typescript title="TypeScript"
  import { AcontextClient } from '@acontext/acontext';

  const client = new AcontextClient({ apiKey: "..." });

  try {
      const result = await client.sessions.copy("invalid-uuid");
  } catch (error) {
      const message = error.message || String(error);
      
      if (message.includes("SESSION_NOT_FOUND")) {
          console.log("Session does not exist or you don't have access");
      } else if (message.includes("SESSION_TOO_LARGE")) {
          console.log("Session is too large to copy synchronously");
      } else {
          console.log(`Copy failed: ${error}`);
      }
  }
  ```
</CodeGroup>

Common Patterns [#common-patterns]

Experiment and Compare [#experiment-and-compare]

Copy a session to try different approaches, then compare results:

<CodeGroup>
  ```python title="Python"
  result = client.sessions.copy(session_id=original_id)
  experimental_id = result.new_session_id

  client.sessions.store_message(
      session_id=experimental_id,
      blob={"role": "user", "content": "Alternative approach..."},
      format="openai"
  )

  original = client.sessions.get_token_counts(session_id=original_id)
  experimental = client.sessions.get_token_counts(session_id=experimental_id)

  print(f"Original: {original.total_tokens} tokens")
  print(f"Experimental: {experimental.total_tokens} tokens")
  ```

  ```typescript title="TypeScript"
  const result = await client.sessions.copy(originalId);
  const experimentalId = result.newSessionId;

  await client.sessions.storeMessage(
      experimentalId,
      { role: "user", content: "Alternative approach..." },
      { format: "openai" }
  );

  const original = await client.sessions.getTokenCounts(originalId);
  const experimental = await client.sessions.getTokenCounts(experimentalId);

  console.log(`Original: ${original.totalTokens} tokens`);
  console.log(`Experimental: ${experimental.totalTokens} tokens`);
  ```
</CodeGroup>

Checkpoint Before Major Changes [#checkpoint-before-major-changes]

Create a checkpoint before making significant changes:

<CodeGroup>
  ```python title="Python"
  checkpoint = client.sessions.copy(session_id=session_id)
  print(f"Checkpoint created: {checkpoint.new_session_id}")

  client.sessions.store_message(
      session_id=session_id,
      blob={"role": "user", "content": "Major change..."},
      format="openai"
  )
  ```

  ```typescript title="TypeScript"
  const checkpoint = await client.sessions.copy(sessionId);
  console.log(`Checkpoint created: ${checkpoint.newSessionId}`);

  await client.sessions.storeMessage(
      sessionId,
      { role: "user", content: "Major change..." },
      { format: "openai" }
  );
  ```
</CodeGroup>

Template Sessions [#template-sessions]

Create a base session as a template and copy it for each new conversation:

<CodeGroup>
  ```python title="Python"
  template_id = "template-session-uuid"
  client.sessions.store_message(
      session_id=template_id,
      blob={"role": "system", "content": "You are a helpful assistant..."},
      format="openai"
  )

  new_conversation = client.sessions.copy(session_id=template_id)
  ```

  ```typescript title="TypeScript"
  const templateId = "template-session-uuid";
  await client.sessions.storeMessage(
      templateId,
      { role: "system", content: "You are a helpful assistant..." },
      { format: "openai" }
  );

  const newConversation = await client.sessions.copy(templateId);
  ```
</CodeGroup>

Performance [#performance]

Copy operations typically complete in:

* **\< 1 second**: Sessions with \< 100 messages
* **\< 3 seconds**: Sessions with \< 1000 messages
* **\< 5 seconds**: Sessions with \< 5000 messages

The operation is atomic - either the entire copy succeeds or fails with no partial state.
