Headless mode
Run Letta Code non-interactively for scripting and automation
Headless mode allows you to run Letta Code non-interactively, making it easy to integrate into scripts, CI/CD pipelines, or compose with other UNIX tools.
Basic usage
Section titled “Basic usage”Use the -p flag to pass a prompt directly:
letta -p "Look around this repo and write a README.md documenting it"You can also pipe input to Letta Code:
echo "Explain this error" | letta -pOutput formats
Section titled “Output formats”Letta Code supports three output formats in headless mode:
Text (default)
Section titled “Text (default)”Returns the agent’s response as plain text:
letta -p "What files are in this directory?"Returns a structured JSON response with metadata:
letta -p "List all TypeScript files" --output-format json{ "type": "result", "result": "Found 15 TypeScript files...", "agent_id": "agent-abc123", "conversation_id": "conversation-xyz789", "usage": { "prompt_tokens": 1250, "completion_tokens": 89 }}Stream JSON
Section titled “Stream JSON”Returns line-delimited JSON events for real-time streaming. This is useful for preventing timeouts and getting incremental progress:
letta -p "Explain this codebase" --output-format stream-jsonEach line is a JSON event:
{"type":"system","subtype":"init","agent_id":"agent-...","conversation_id":"conversation-...","session_id":"agent-...","model":"claude-sonnet-4-5","tools":[...]}{"type":"message","message_type":"reasoning_message","reasoning":"The user is asking...","otid":"...","seq_id":1}{"type":"message","message_type":"assistant_message","content":"Here's an overview...","otid":"...","seq_id":5}{"type":"message","message_type":"stop_reason","stop_reason":"end_turn"}{"type":"message","message_type":"usage_statistics","prompt_tokens":294,"completion_tokens":97}{"type":"result","subtype":"success","result":"Here's an overview...","agent_id":"...","conversation_id":"...","session_id":"...","uuid":"..."}Messages are streamed at the token level - each chunk has the same otid (output turn ID) and incrementing seq_id.
Bidirectional mode
Section titled “Bidirectional mode”For programmatic control, use --input-format stream-json to enable bidirectional JSON communication over stdin/stdout. This allows external programs to send messages and receive responses in a structured format.
letta -p --input-format stream-json --output-format stream-jsonInput message types
Section titled “Input message types”Send JSON messages to stdin (one per line):
{"type": "user", "message": {"role": "user", "content": "What files are here?"}}{"type": "control_request", "request_id": "init_1", "request": {"subtype": "initialize"}}{"type": "control_request", "request_id": "int_1", "request": {"subtype": "interrupt"}}Output message types
Section titled “Output message types”The CLI emits JSON messages to stdout:
{"type": "system", "subtype": "init", "agent_id": "agent-xxx", "conversation_id": "conversation-xxx", "session_id": "agent-xxx", "model": "...", "tools": [...]}{"type": "control_response", "response": {"subtype": "success", "request_id": "init_1", "response": {...}}}{"type": "message", "message_type": "assistant_message", "content": "Hello!", "session_id": "...", "uuid": "..."}{"type": "result", "subtype": "success", "result": "Hello!", "session_id": "...", "agent_id": "...", "conversation_id": "..."}Multi-turn conversations
Section titled “Multi-turn conversations”The process stays alive until stdin closes, allowing multi-turn conversations:
(echo '{"type": "user", "message": {"role": "user", "content": "Remember: secret is BANANA"}}'sleep 5echo '{"type": "user", "message": {"role": "user", "content": "What was the secret?"}}') | letta -p --input-format stream-json --output-format stream-jsonToken-level streaming
Section titled “Token-level streaming”Add --include-partial-messages to receive token-level streaming events:
letta -p --input-format stream-json --output-format stream-json --include-partial-messagesThis wraps each chunk in a stream_event:
{"type": "stream_event", "event": {"message_type": "assistant_message", "content": "Hel"}, "session_id": "...", "uuid": "..."}Agent and conversation selection
Section titled “Agent and conversation selection”By default, headless mode uses the last agent from the current directory and its “default” conversation. Your agent retains memory across all runs, and the default conversation preserves message history between sessions.
To create a new conversation for parallel sessions, use --new:
letta -p "..." --newletta -p "..." --new-agentletta -p "..." --agent <agent-id>letta -p "..." --continueletta -p "..." --conversation <conversation-id>The JSON and stream-json output formats include a conversation_id field, which you can use to continue the same conversation in subsequent calls:
result=$(letta -p "Start a new task" --output-format json)conv_id=$(echo $result | jq -r '.conversation_id')
# Continue the same conversationletta -p "Continue where we left off" --conversation $conv_id --output-format jsonModel selection
Section titled “Model selection”Specify a model for the headless run:
letta -p "..." --model sonnet-4.5letta -p "..." -m gpt-5-codexletta -p "..." -m haikuSee Models for the full list of supported model IDs.
Permission control
Section titled “Permission control”Auto-allow all tools
Section titled “Auto-allow all tools”Use --yolo to bypass all permission prompts (use with caution):
letta -p "Refactor this file" --yoloRestrict available tools
Section titled “Restrict available tools”The --tools flag controls which tools are attached to the agent (removing them from the context window entirely):
letta -p "Analyze this codebase" --tools "Read,Glob,Grep"letta -p "What do you think about this approach?" --tools ""This is different from --allowedTools/--disallowedTools which control permissions but keep tools in context. See Permissions for more details.
Permission modes
Section titled “Permission modes”letta -p "Fix the type errors" --permission-mode acceptEditsletta -p "Review this PR" --permission-mode planAdvanced options
Section titled “Advanced options”Resume by name
Section titled “Resume by name”Use -n or --name to resume an agent by name (case-insensitive). Matches pinned agents or recent agents:
letta -p "Continue where we left off" --name myprojectSystem prompt configuration
Section titled “System prompt configuration”Customize the agent’s system prompt when creating new agents:
letta -p "..." --new-agent --system letta-claudeletta -p "..." --new-agent --system-custom "You are a Python expert who writes clean code."letta -p "..." --new-agent --system letta-claude --system-append "Always respond in Spanish."Available presets:
default/letta-claude- Full Letta Code prompt (Claude-optimized)letta-codex- Full Letta Code prompt (Codex-optimized)letta-gemini- Full Letta Code prompt (Gemini-optimized)claude- Basic Claude (no skills/memory instructions)codex- Basic Codexgemini- Basic Gemini
Memory block configuration
Section titled “Memory block configuration”Customize which memory blocks the agent uses:
letta -p "..." --new-agent --init-blocks "persona,project"letta -p "..." --new-agent --init-blocks "persona,project" \ --block-value persona="You are a Go expert" \ --block-value project="CLI tool for Docker"letta -p "..." --new-agent --memory-blocks '[ {"label": "context", "value": "API documentation for Acme Corp..."}, {"label": "rules", "value": "Always use TypeScript"}]'letta -p "..." --new-agent --init-blocks ""Available preset blocks:
persona- Agent’s personality and behaviorhuman- Information about the userproject- Current project context
Core blocks (always included):
skills- Available skills directoryloaded_skills- Currently loaded skill instructions
Toolset override
Section titled “Toolset override”Force a specific toolset instead of auto-detection based on model:
letta -p "..." --toolset codex # Codex-style toolsletta -p "..." --toolset gemini # Gemini-style toolsletta -p "..." --toolset default # Default Letta toolsBase tools configuration
Section titled “Base tools configuration”When creating a new agent with --new-agent, specify which base tools to attach:
letta -p "..." --new-agent --base-tools "memory,web_search"Create from AgentFile
Section titled “Create from AgentFile”Create an agent from an AgentFile template:
letta -p "..." --from-af ./my-agent.afSystem prompt configuration
Section titled “System prompt configuration”Customize the agent’s system prompt:
letta -p "..." --system-custom "You are a helpful assistant that only responds in haiku."letta -p "..." --system-append "Always respond in JSON format."Memory block configuration
Section titled “Memory block configuration”Configure memory blocks when creating agents:
letta -p "..." --new-agent --memory-blocks '{"persona": "You are a code reviewer", "project": "React app"}'letta -p "..." --block-value "persona=You are a security auditor" --block-value "project=Backend API"Examples
Section titled “Examples”Automated tasks
Section titled “Automated tasks”letta -p "Run the linter and fix any errors" --yoloStructured output for scripts
Section titled “Structured output for scripts”Use JSON output to parse results programmatically:
result=$(letta -p "What is the main entry point of this project?" --output-format json)echo $result | jq '.result'Read-only analysis
Section titled “Read-only analysis”Use --tools to restrict the agent to read-only operations:
letta -p "Review this codebase for potential security issues" --tools "Read,Glob,Grep"Scheduled tasks with cron
Section titled “Scheduled tasks with cron”Run Letta Code on a schedule using cron:
0 9 * * * cd /path/to/project && letta -p "Review recent changes and summarize any issues" --tools "Read,Glob,Grep" --output-format json >> /var/log/letta-review.log 2>&10 10 * * 1 cd /path/to/project && letta -p "Check for outdated dependencies and security vulnerabilities" --yolo >> /var/log/letta-deps.log 2>&1