fix: make --new-agent use default conversation (#595)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2026-01-19 13:33:00 -08:00
committed by GitHub
parent a526614e28
commit 03a2cfc2ed
4 changed files with 40 additions and 18 deletions

View File

@@ -328,8 +328,9 @@ function buildSubagentArgs(
// conversation_id is sufficient (headless derives agent from it)
args.push("--conv", existingConversationId);
} else if (existingAgentId) {
// agent_id only - headless creates new conversation
args.push("--agent", existingAgentId);
// agent_id only - use --new to create a new conversation for thread safety
// (multiple parallel calls to the same agent need separate conversations)
args.push("--agent", existingAgentId, "--new");
}
// Don't pass --system (existing agent keeps its prompt)
// Don't pass --model (existing agent keeps its model)

View File

@@ -641,16 +641,15 @@ export async function handleHeadlessCommand(
);
process.exit(1);
}
} else if (forceNewConversation || forceNew) {
// --new flag (new conversation) or --new-agent (new agent): create a new conversation
// When creating a new agent, always create a new conversation alongside it
} else if (forceNewConversation) {
// --new flag: create a new conversation (for concurrent sessions)
const conversation = await client.conversations.create({
agent_id: agent.id,
isolated_block_labels: isolatedBlockLabels,
});
conversationId = conversation.id;
} else {
// Default: use the agent's "default" conversation (OG single-threaded behavior)
// Default (including --new-agent, --agent): use the agent's "default" conversation
conversationId = "default";
}
markMilestone("HEADLESS_CONVERSATION_READY");

View File

@@ -1731,16 +1731,15 @@ async function main(): Promise<void> {
}
throw error;
}
} else if (forceNewConversation || forceNew) {
// --new flag (new conversation) or --new-agent (new agent): create a new conversation
// When creating a new agent, always create a new conversation alongside it
} else if (forceNewConversation) {
// --new flag: create a new conversation (for concurrent sessions)
const conversation = await client.conversations.create({
agent_id: agent.id,
isolated_block_labels: [...ISOLATED_BLOCK_LABELS],
});
conversationIdToUse = conversation.id;
} else {
// Default: use the agent's "default" conversation (OG single-threaded behavior)
// Default (including --new-agent): use the agent's "default" conversation
conversationIdToUse = "default";
// Load message history from the default conversation

View File

@@ -187,7 +187,6 @@ describe("Startup Flow - Invalid Inputs", () => {
describe("Startup Flow - Integration", () => {
// Store created agent/conversation IDs for cleanup and reuse
let testAgentId: string | null = null;
let testConversationId: string | null = null;
test(
"--new-agent creates agent and responds",
@@ -214,7 +213,6 @@ describe("Startup Flow - Integration", () => {
// Save for later tests
testAgentId = output.agent_id;
testConversationId = output.conversation_id;
},
{ timeout: 130000 },
);
@@ -253,16 +251,41 @@ describe("Startup Flow - Integration", () => {
test(
"--conversation with valid ID derives agent and uses conversation",
async () => {
// Skip if previous test didn't create an agent/conversation
if (!testAgentId || !testConversationId) {
console.log("Skipping: no test conversation available");
// Skip if previous test didn't create an agent
if (!testAgentId) {
console.log("Skipping: no test agent available");
return;
}
// First, create a real conversation with --new (since --new-agent uses "default")
const createResult = await runCli(
[
"--agent",
testAgentId,
"--new",
"-m",
"haiku",
"-p",
"Say CREATED",
"--output-format",
"json",
],
{ timeoutMs: 120000 },
);
expect(createResult.exitCode).toBe(0);
const createJsonStart = createResult.stdout.indexOf("{");
const createOutput = JSON.parse(
createResult.stdout.slice(createJsonStart),
);
const realConversationId = createOutput.conversation_id;
expect(realConversationId).toBeDefined();
expect(realConversationId).not.toBe("default");
// Now test that --conversation can derive the agent from this conversation
const result = await runCli(
[
"--conversation",
testConversationId,
realConversationId,
"-m",
"haiku",
"-p",
@@ -279,9 +302,9 @@ describe("Startup Flow - Integration", () => {
// Should use the same agent that owns the conversation
expect(output.agent_id).toBe(testAgentId);
// Should use the specified conversation
expect(output.conversation_id).toBe(testConversationId);
expect(output.conversation_id).toBe(realConversationId);
},
{ timeout: 130000 },
{ timeout: 180000 },
);
test(