From 7d73219c50278db95ca3724610706cf140921bcd Mon Sep 17 00:00:00 2001 From: Devansh Jain <31609257+devanshrj@users.noreply.github.com> Date: Fri, 19 Dec 2025 17:16:21 -0800 Subject: [PATCH] chore: Add `--system` flag for existing agents + update system prompt variable names (#328) --- src/agent/create.ts | 8 ++--- src/agent/modify.ts | 66 ++++++++++++++++++++++++++++++++++++--- src/agent/promptAssets.ts | 14 ++++----- src/cli/App.tsx | 6 ++-- src/headless.ts | 27 +++++++--------- src/index.ts | 65 +++++++++++++++++++++++--------------- 6 files changed, 127 insertions(+), 59 deletions(-) diff --git a/src/agent/create.ts b/src/agent/create.ts index 8217832..bce49a9 100644 --- a/src/agent/create.ts +++ b/src/agent/create.ts @@ -53,7 +53,7 @@ export async function createAgent( skillsDirectory?: string, parallelToolCalls = true, enableSleeptime = false, - systemPrompt?: string, + systemPromptId?: string, initBlocks?: string[], baseTools?: string[], ) { @@ -202,13 +202,13 @@ export async function createAgent( const modelUpdateArgs = getModelUpdateArgs(modelHandle); const contextWindow = (modelUpdateArgs?.context_window as number) || 200_000; - // Resolve system prompt (ID, subagent name, or literal content) - const resolvedSystemPrompt = await resolveSystemPrompt(systemPrompt); + // Resolve system prompt ID to content + const systemPromptContent = await resolveSystemPrompt(systemPromptId); // Create agent with all block IDs (existing + newly created) const agent = await client.agents.create({ agent_type: "letta_v1_agent" as AgentType, - system: resolvedSystemPrompt, + system: systemPromptContent, name, description: `Letta Code agent created in ${process.cwd()}`, embedding: embeddingModel, diff --git a/src/agent/modify.ts b/src/agent/modify.ts index 0f02932..e0f5459 100644 --- a/src/agent/modify.ts +++ b/src/agent/modify.ts @@ -2,6 +2,7 @@ // Utilities for modifying agent configuration import type { + AgentState, AnthropicModelSettings, GoogleAIModelSettings, OpenAIModelSettings, @@ -316,21 +317,21 @@ export interface SystemPromptUpdateResult { } /** - * Updates an agent's system prompt. + * Updates an agent's system prompt with raw content. * * @param agentId - The agent ID - * @param systemPrompt - The new system prompt content + * @param systemPromptContent - The raw system prompt content to update * @returns Result with success status and message */ -export async function updateAgentSystemPrompt( +export async function updateAgentSystemPromptRaw( agentId: string, - systemPrompt: string, + systemPromptContent: string, ): Promise { try { const client = await getClient(); await client.agents.update(agentId, { - system: systemPrompt, + system: systemPromptContent, }); return { @@ -344,3 +345,58 @@ export async function updateAgentSystemPrompt( }; } } + +/** + * Result from updating a system prompt on an agent + */ +export interface UpdateSystemPromptResult { + success: boolean; + message: string; + agent: AgentState | null; +} + +/** + * Updates an agent's system prompt by ID or subagent name. + * Resolves the ID to content, updates the agent, and returns the refreshed agent state. + * + * @param agentId - The agent ID to update + * @param systemPromptId - System prompt ID (e.g., "codex") or subagent name (e.g., "explore") + * @returns Result with success status, message, and updated agent state + */ +export async function updateAgentSystemPrompt( + agentId: string, + systemPromptId: string, +): Promise { + try { + const { resolveSystemPrompt } = await import("./promptAssets"); + const systemPromptContent = await resolveSystemPrompt(systemPromptId); + + const updateResult = await updateAgentSystemPromptRaw( + agentId, + systemPromptContent, + ); + if (!updateResult.success) { + return { + success: false, + message: updateResult.message, + agent: null, + }; + } + + // Re-fetch agent to get updated state + const client = await getClient(); + const agent = await client.agents.retrieve(agentId); + + return { + success: true, + message: "System prompt applied successfully", + agent, + }; + } catch (error) { + return { + success: false, + message: `Failed to apply system prompt: ${error instanceof Error ? error.message : String(error)}`, + agent: null, + }; + } +} diff --git a/src/agent/promptAssets.ts b/src/agent/promptAssets.ts index 613484f..c7b9a37 100644 --- a/src/agent/promptAssets.ts +++ b/src/agent/promptAssets.ts @@ -99,26 +99,26 @@ export const SYSTEM_PROMPTS: SystemPromptOption[] = [ ]; /** - * Resolve a system prompt string to its content. + * Resolve a system prompt ID to its content. * * Resolution order: - * 1. If it matches a systemPromptId from SYSTEM_PROMPTS, use its content + * 1. If it matches an ID from SYSTEM_PROMPTS, use its content * 2. If it matches a subagent name, use that subagent's system prompt * 3. Otherwise, use the default system prompt * - * @param systemPromptInput - The system prompt ID or subagent name + * @param systemPromptId - The system prompt ID (e.g., "codex") or subagent name (e.g., "explore") * @returns The resolved system prompt content */ export async function resolveSystemPrompt( - systemPromptInput: string | undefined, + systemPromptId: string | undefined, ): Promise { // No input - use default - if (!systemPromptInput) { + if (!systemPromptId) { return SYSTEM_PROMPT; } // 1. Check if it matches a system prompt ID - const matchedPrompt = SYSTEM_PROMPTS.find((p) => p.id === systemPromptInput); + const matchedPrompt = SYSTEM_PROMPTS.find((p) => p.id === systemPromptId); if (matchedPrompt) { return matchedPrompt.content; } @@ -126,7 +126,7 @@ export async function resolveSystemPrompt( // 2. Check if it matches a subagent name const { getAllSubagentConfigs } = await import("./subagents"); const subagentConfigs = await getAllSubagentConfigs(); - const matchedSubagent = subagentConfigs[systemPromptInput]; + const matchedSubagent = subagentConfigs[systemPromptId]; if (matchedSubagent) { return matchedSubagent.systemPrompt; } diff --git a/src/cli/App.tsx b/src/cli/App.tsx index ae0c3b3..1da9267 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -3916,8 +3916,10 @@ ${recentCommits} refreshDerived(); // Update the agent's system prompt - const { updateAgentSystemPrompt } = await import("../agent/modify"); - const result = await updateAgentSystemPrompt( + const { updateAgentSystemPromptRaw } = await import( + "../agent/modify" + ); + const result = await updateAgentSystemPromptRaw( agentId, selectedPrompt.content, ); diff --git a/src/headless.ts b/src/headless.ts index e017daa..7421e52 100644 --- a/src/headless.ts +++ b/src/headless.ts @@ -115,7 +115,7 @@ export async function handleHeadlessCommand( const specifiedAgentId = values.agent as string | undefined; const shouldContinue = values.continue as boolean | undefined; const forceNew = values.new as boolean | undefined; - const specifiedSystem = values.system as string | undefined; + const systemPromptId = values.system as string | undefined; const initBlocksRaw = values["init-blocks"] as string | undefined; const baseToolsRaw = values["base-tools"] as string | undefined; const sleeptimeFlag = (values.sleeptime as boolean | undefined) ?? undefined; @@ -209,7 +209,7 @@ export async function handleHeadlessCommand( skillsDirectory, true, // parallelToolCalls always enabled sleeptimeFlag ?? settings.enableSleeptime, - specifiedSystem, + systemPromptId, initBlocks, baseTools, ); @@ -226,7 +226,7 @@ export async function handleHeadlessCommand( skillsDirectory, true, sleeptimeFlag ?? settings.enableSleeptime, - specifiedSystem, + systemPromptId, initBlocks, baseTools, ); @@ -275,7 +275,7 @@ export async function handleHeadlessCommand( skillsDirectory, true, // parallelToolCalls always enabled sleeptimeFlag ?? settings.enableSleeptime, - specifiedSystem, + systemPromptId, undefined, undefined, ); @@ -292,7 +292,7 @@ export async function handleHeadlessCommand( skillsDirectory, true, sleeptimeFlag ?? settings.enableSleeptime, - specifiedSystem, + systemPromptId, undefined, undefined, ); @@ -311,7 +311,7 @@ export async function handleHeadlessCommand( ); // If resuming and a model or system prompt was specified, apply those changes - if (isResumingAgent && (model || specifiedSystem)) { + if (isResumingAgent && (model || systemPromptId)) { if (model) { const { resolveModel } = await import("./agent/model"); const modelHandle = resolveModel(model); @@ -334,19 +334,14 @@ export async function handleHeadlessCommand( } } - if (specifiedSystem) { + if (systemPromptId) { const { updateAgentSystemPrompt } = await import("./agent/modify"); - const { SYSTEM_PROMPTS } = await import("./agent/promptAssets"); - const systemPromptOption = SYSTEM_PROMPTS.find( - (p) => p.id === specifiedSystem, - ); - if (!systemPromptOption) { - console.error(`Error: Invalid system prompt "${specifiedSystem}"`); + const result = await updateAgentSystemPrompt(agent.id, systemPromptId); + if (!result.success || !result.agent) { + console.error(`Failed to update system prompt: ${result.message}`); process.exit(1); } - await updateAgentSystemPrompt(agent.id, systemPromptOption.content); - // Refresh agent state after system prompt update - agent = await client.agents.retrieve(agent.id); + agent = result.agent; } } diff --git a/src/index.ts b/src/index.ts index a3f0e58..11f1b5a 100755 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,7 @@ OPTIONS --base-tools Comma-separated base tools to attach when using --new (e.g., "memory,web_search,conversation_search") -a, --agent Use a specific agent ID -m, --model Model ID or handle (e.g., "opus-4.5" or "anthropic/claude-opus-4-5") - -s, --system System prompt ID (e.g., "codex", "gpt-5.1", "review") + -s, --system System prompt ID or subagent name (applies to new or existing agent) --toolset Force toolset: "codex", "default", or "gemini" (overrides model-based auto-selection) -p, --prompt Headless prompt mode --output-format Output format for headless mode (text, json, stream-json) @@ -308,7 +308,7 @@ async function main(): Promise { const baseToolsRaw = values["base-tools"] as string | undefined; const specifiedAgentId = (values.agent as string | undefined) ?? null; const specifiedModel = (values.model as string | undefined) ?? undefined; - const specifiedSystem = (values.system as string | undefined) ?? undefined; + const systemPromptId = (values.system as string | undefined) ?? undefined; const specifiedToolset = (values.toolset as string | undefined) ?? undefined; const skillsDirectory = (values.skills as string | undefined) ?? undefined; const sleeptimeFlag = (values.sleeptime as boolean | undefined) ?? undefined; @@ -379,7 +379,7 @@ async function main(): Promise { } // Validate system prompt if provided (can be a system prompt ID or subagent name) - if (specifiedSystem) { + if (systemPromptId) { const { SYSTEM_PROMPTS } = await import("./agent/promptAssets"); const { getAllSubagentConfigs } = await import("./agent/subagents"); @@ -387,13 +387,13 @@ async function main(): Promise { const subagentConfigs = await getAllSubagentConfigs(); const validSubagentNames = Object.keys(subagentConfigs); - const isValidSystemPrompt = validSystemPrompts.includes(specifiedSystem); - const isValidSubagent = validSubagentNames.includes(specifiedSystem); + const isValidSystemPrompt = validSystemPrompts.includes(systemPromptId); + const isValidSubagent = validSubagentNames.includes(systemPromptId); if (!isValidSystemPrompt && !isValidSubagent) { const allValid = [...validSystemPrompts, ...validSubagentNames]; console.error( - `Error: Invalid system prompt "${specifiedSystem}". Must be one of: ${allValid.join(", ")}.`, + `Error: Invalid system prompt "${systemPromptId}". Must be one of: ${allValid.join(", ")}.`, ); process.exit(1); } @@ -593,7 +593,7 @@ async function main(): Promise { baseTools, agentIdArg, model, - system, + systemPromptId, toolset, skillsDirectory, fromAfFile, @@ -604,7 +604,7 @@ async function main(): Promise { baseTools?: string[]; agentIdArg: string | null; model?: string; - system?: string; + systemPromptId?: string; toolset?: "codex" | "default" | "gemini"; skillsDirectory?: string; fromAfFile?: string; @@ -763,7 +763,24 @@ async function main(): Promise { if (!agent && agentIdArg) { try { agent = await client.agents.retrieve(agentIdArg); - // console.log(`Using agent ${agentIdArg}...`); + + // Apply --system flag to existing agent if provided + if (systemPromptId) { + const { updateAgentSystemPrompt } = await import( + "./agent/modify" + ); + const result = await updateAgentSystemPrompt( + agent.id, + systemPromptId, + ); + if (!result.success || !result.agent) { + console.error( + `Failed to update system prompt: ${result.message}`, + ); + process.exit(1); + } + agent = result.agent; + } } catch (error) { console.error( `Agent ${agentIdArg} not found (error: ${JSON.stringify(error)})`, @@ -788,7 +805,7 @@ async function main(): Promise { skillsDirectory, true, // parallelToolCalls always enabled sleeptimeFlag ?? settings.enableSleeptime, - system, + systemPromptId, initBlocks, baseTools, ); @@ -810,7 +827,7 @@ async function main(): Promise { skillsDirectory, true, sleeptimeFlag ?? settings.enableSleeptime, - system, + systemPromptId, initBlocks, baseTools, ); @@ -865,7 +882,7 @@ async function main(): Promise { skillsDirectory, true, // parallelToolCalls always enabled sleeptimeFlag ?? settings.enableSleeptime, - system, + systemPromptId, undefined, undefined, ); @@ -887,7 +904,7 @@ async function main(): Promise { skillsDirectory, true, sleeptimeFlag ?? settings.enableSleeptime, - system, + systemPromptId, undefined, undefined, ); @@ -968,7 +985,7 @@ async function main(): Promise { setIsResumingSession(resuming); // If resuming and a model or system prompt was specified, apply those changes - if (resuming && (model || system)) { + if (resuming && (model || systemPromptId)) { if (model) { const { resolveModel } = await import("./agent/model"); const modelHandle = resolveModel(model); @@ -992,19 +1009,17 @@ async function main(): Promise { } } - if (system) { + if (systemPromptId) { const { updateAgentSystemPrompt } = await import("./agent/modify"); - const { SYSTEM_PROMPTS } = await import("./agent/promptAssets"); - const systemPromptOption = SYSTEM_PROMPTS.find( - (p) => p.id === system, + const result = await updateAgentSystemPrompt( + agent.id, + systemPromptId, ); - if (!systemPromptOption) { - console.error(`Error: Invalid system prompt "${system}"`); + if (!result.success || !result.agent) { + console.error(`Error: ${result.message}`); process.exit(1); } - await updateAgentSystemPrompt(agent.id, systemPromptOption.content); - // Refresh agent state after system prompt update - agent = await client.agents.retrieve(agent.id); + agent = result.agent; } } @@ -1035,7 +1050,7 @@ async function main(): Promise { forceNew, agentIdArg, model, - system, + systemPromptId, fromAfFile, loadingState, ]); @@ -1078,7 +1093,7 @@ async function main(): Promise { baseTools: baseTools, agentIdArg: specifiedAgentId, model: specifiedModel, - system: specifiedSystem, + systemPromptId: systemPromptId, toolset: specifiedToolset as "codex" | "default" | "gemini" | undefined, skillsDirectory: skillsDirectory, fromAfFile: fromAfFile,