diff --git a/src/agent/check-approval.ts b/src/agent/check-approval.ts
index c0cd15c..bb88586 100644
--- a/src/agent/check-approval.ts
+++ b/src/agent/check-approval.ts
@@ -6,7 +6,7 @@ import { APIError } from "@letta-ai/letta-client/core/error";
import type { AgentState } from "@letta-ai/letta-client/resources/agents/agents";
import type { Message } from "@letta-ai/letta-client/resources/agents/messages";
import type { ApprovalRequest } from "../cli/helpers/stream";
-import { debugWarn } from "../utils/debug";
+import { debugLog, debugWarn } from "../utils/debug";
// Backfill should feel like "the last turn(s)", not "the last N raw messages".
// Tool-heavy turns can generate many tool_call/tool_return messages that would
@@ -344,16 +344,21 @@ export async function getResumeData(
// Use conversations API for explicit conversations,
// use agents API for "default" or no conversationId (agent's primary message history)
- const useConversationsApi = conversationId && conversationId !== "default";
+ const useConversationsApi =
+ conversationId &&
+ conversationId !== "default" &&
+ !conversationId.startsWith("agent-");
- if (process.env.DEBUG) {
- console.log(
- `[DEBUG] getResumeData: conversationId=${conversationId}, useConversationsApi=${useConversationsApi}, agentId=${agent.id}`,
+ if (conversationId?.startsWith("agent-")) {
+ debugWarn(
+ "check-approval",
+ `getResumeData called with agent ID as conversationId: ${conversationId}\n${new Error().stack}`,
);
}
if (useConversationsApi) {
// Get conversation to access in_context_message_ids (source of truth)
+ debugLog("conversations", `retrieve(${conversationId}) [getResumeData]`);
const conversation = await client.conversations.retrieve(conversationId);
inContextMessageIds = conversation.in_context_message_ids;
diff --git a/src/cli/App.tsx b/src/cli/App.tsx
index 9101bff..6afe942 100644
--- a/src/cli/App.tsx
+++ b/src/cli/App.tsx
@@ -3280,6 +3280,10 @@ export default function App({
try {
const client = await getClient();
+ debugLog(
+ "conversations",
+ `retrieve(${conversationId}) [syncConversationModel]`,
+ );
const conversation =
await client.conversations.retrieve(conversationId);
if (cancelled) return;
@@ -6154,7 +6158,9 @@ export default function App({
// Build success message
const agentLabel = agent.name || targetAgentId;
const isSpecificConv =
- opts?.conversationId && opts.conversationId !== "default";
+ opts?.conversationId &&
+ opts.conversationId !== "default" &&
+ !opts?.conversationId.startsWith("agent-");
const successOutput = isSpecificConv
? [
`Switched to **${agentLabel}**`,
@@ -8695,7 +8701,7 @@ export default function App({
// Build export parameters (include conversation_id if in specific conversation)
const exportParams: { conversation_id?: string } = {};
- if (conversationId !== "default") {
+ if (conversationId !== "default" && conversationId !== agentId) {
exportParams.conversation_id = conversationId;
}
@@ -12914,15 +12920,16 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
: `letta --agent ${agentId}`}
{/* Only show conversation hint if not on default (default is resumed automatically) */}
- {conversationId !== "default" && (
- <>
-
- Resume this conversation with:
-
- {`letta --conv ${conversationId}`}
-
- >
- )}
+ {conversationId !== "default" &&
+ conversationId !== agentId && (
+ <>
+
+ Resume this conversation with:
+
+ {`letta --conv ${conversationId}`}
+
+ >
+ )}
);
})()}
diff --git a/src/cli/components/AgentInfoBar.tsx b/src/cli/components/AgentInfoBar.tsx
index 7044356..e689949 100644
--- a/src/cli/components/AgentInfoBar.tsx
+++ b/src/cli/components/AgentInfoBar.tsx
@@ -177,7 +177,9 @@ export const AgentInfoBar = memo(function AgentInfoBar({
{/* Phantom alien row + Conversation ID */}
{alienLines[3]}
- {conversationId && conversationId !== "default" ? (
+ {conversationId &&
+ conversationId !== "default" &&
+ !conversationId.startsWith("agent-") ? (
{truncateText(conversationId, rightWidth)}
diff --git a/src/headless.ts b/src/headless.ts
index 795b86b..d43158e 100644
--- a/src/headless.ts
+++ b/src/headless.ts
@@ -114,6 +114,7 @@ import type {
StreamEvent,
SystemInitMessage,
} from "./types/protocol";
+import { debugLog } from "./utils/debug";
import {
markMilestone,
measureSinceMilestone,
@@ -526,7 +527,10 @@ export async function handleHeadlessCommand(
// Validate shared mutual-exclusion rules for startup flags.
try {
validateFlagConflicts({
- guard: specifiedConversationId && specifiedConversationId !== "default",
+ guard:
+ specifiedConversationId &&
+ specifiedConversationId !== "default" &&
+ !specifiedConversationId.startsWith("agent-"),
checks: [
{
when: specifiedAgentId,
@@ -730,8 +734,16 @@ export async function handleHeadlessCommand(
// Priority 0: --conversation derives agent from conversation ID.
// "default" is a virtual agent-scoped conversation (not a retrievable conv-*).
// It requires --agent and should not hit conversations.retrieve().
- if (specifiedConversationId && specifiedConversationId !== "default") {
+ if (
+ specifiedConversationId &&
+ specifiedConversationId !== "default" &&
+ !specifiedConversationId.startsWith("agent-")
+ ) {
try {
+ debugLog(
+ "conversations",
+ `retrieve(${specifiedConversationId}) [headless conv→agent lookup]`,
+ );
const conversation = await client.conversations.retrieve(
specifiedConversationId,
);
@@ -1007,6 +1019,10 @@ export async function handleHeadlessCommand(
} else {
// User specified an explicit conversation to resume - validate it exists
try {
+ debugLog(
+ "conversations",
+ `retrieve(${specifiedConversationId}) [headless --conv validate]`,
+ );
await client.conversations.retrieve(specifiedConversationId);
conversationId = specifiedConversationId;
} catch {
@@ -1030,6 +1046,10 @@ export async function handleHeadlessCommand(
} else {
// Verify the conversation still exists
try {
+ debugLog(
+ "conversations",
+ `retrieve(${lastSession.conversationId}) [headless lastSession resume]`,
+ );
await client.conversations.retrieve(lastSession.conversationId);
conversationId = lastSession.conversationId;
} catch {
diff --git a/src/index.ts b/src/index.ts
index 62085e3..17ed4a9 100755
--- a/src/index.ts
+++ b/src/index.ts
@@ -47,6 +47,7 @@ import { settingsManager } from "./settings-manager";
import { startStartupAutoUpdateCheck } from "./startup-auto-update";
import { telemetry } from "./telemetry";
import { loadTools } from "./tools/manager";
+import { debugLog } from "./utils/debug";
import { markMilestone } from "./utils/timing";
// Stable empty array constants to prevent new references on every render
@@ -629,7 +630,10 @@ async function main(): Promise {
// Validate shared mutual-exclusion rules for startup flags.
try {
validateFlagConflicts({
- guard: specifiedConversationId && specifiedConversationId !== "default",
+ guard:
+ specifiedConversationId &&
+ specifiedConversationId !== "default" &&
+ !specifiedConversationId.startsWith("agent-"),
checks: [
{
when: specifiedAgentId,
@@ -1193,6 +1197,10 @@ async function main(): Promise {
// For explicit conversations, derive agent from conversation
try {
+ debugLog(
+ "conversations",
+ `retrieve(${specifiedConversationId}) [TUI conv→agent lookup]`,
+ );
const conversation = await client.conversations.retrieve(
specifiedConversationId,
);