Documentation Index Fetch the complete documentation index at: https://mintlify.com/block/goose/llms.txt
Use this file to discover all available pages before exploring further.
Sessions in Goose represent individual conversations with the AI agent. Each session maintains its own state, history, configuration, and context, enabling you to work on multiple tasks independently and resume work later.
What is a Session?
A session encapsulates:
Conversation history : All messages exchanged with the agent
Working directory : Where the agent operates on your filesystem
Extension state : Which tools are enabled and their data
Configuration : Model, provider, and recipe being used
Metadata : Creation time, token usage, session name
// From crates/goose/src/session/session_manager.rs
pub struct Session {
pub id : String , // Unique identifier
pub working_dir : PathBuf , // Agent's workspace
pub name : String , // Human-readable name
pub session_type : SessionType , // User/SubAgent/Scheduled/etc
pub created_at : DateTime < Utc >,
pub updated_at : DateTime < Utc >,
pub extension_data : ExtensionData , // Extension state
pub conversation : Option < Conversation >, // Message history
pub recipe : Option < Recipe >, // Active recipe
pub provider_name : Option < String >, // AI provider
pub model_config : Option < ModelConfig >, // Model settings
pub total_tokens : Option < i32 >, // Token counts
// ...
}
Session Types
Goose supports different session types for different purposes:
pub enum SessionType {
User , // Regular user sessions
SubAgent , // Subagent task execution
Scheduled , // Scheduled/automated tasks
Hidden , // Internal/system sessions
Terminal , // Terminal integration sessions
Gateway , // Gateway/proxy sessions
}
User Sessions
Standard interactive sessions:
# Create a new session
goose session create --name "Refactor auth module"
# Resume existing session
goose session resume abc123
# List sessions
goose session list
SubAgent Sessions
Created automatically when spawning subagents:
// Subagent gets its own isolated session
let subagent_session = session_manager . create_session (
SessionType :: SubAgent ,
recipe ,
parent_session_id ,
) . await ? ;
Subagent sessions are:
Isolated from parent session
Have their own conversation history
Can have different extensions/settings
Automatically cleaned up when complete
Session Lifecycle
Creating Sessions
// Via SessionManager
let session = session_manager . create_session (
SessionType :: User ,
working_dir ,
name ,
) . await ? ;
// With recipe
let session = session_manager . create_session_with_recipe (
SessionType :: User ,
recipe ,
recipe_values , // Parameter values
) . await ? ;
Updating Sessions
Goose uses a builder pattern for updates:
session_manager
. update_session ( session_id )
. name ( "New session name" )
. extension_data ( updated_data )
. total_tokens ( Some ( 1500 ))
. apply ()
. await ? ;
Querying Sessions
// Get session by ID
let session = session_manager . get_session ( & session_id ) . await ? ;
// List all user sessions
let sessions = session_manager . list_sessions (
SessionType :: User ,
None , // limit
None , // offset
) . await ? ;
// Search sessions
let sessions = session_manager . search_sessions ( "authentication" ) . await ? ;
Session Storage
Sessions are persisted to SQLite:
~/.config/goose/
└── sessions/
├── sessions.db # SQLite database
└── [session-id]/
├── conversation.json # Message history
└── metadata.json # Session metadata
Database Schema
CREATE TABLE sessions (
id TEXT PRIMARY KEY ,
working_dir TEXT NOT NULL ,
name TEXT NOT NULL ,
user_set_name INTEGER DEFAULT 0 ,
session_type TEXT DEFAULT 'user' ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
total_tokens INTEGER ,
input_tokens INTEGER ,
output_tokens INTEGER ,
schedule_id TEXT ,
recipe TEXT , -- JSON
user_recipe_values TEXT , -- JSON
provider_name TEXT ,
model_config TEXT -- JSON
);
CREATE TABLE messages (
id TEXT PRIMARY KEY ,
session_id TEXT NOT NULL ,
role TEXT NOT NULL , -- 'user' or 'assistant'
content TEXT NOT NULL , -- JSON
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES sessions (id)
);
Conversation Management
Each session maintains a conversation object:
pub struct Conversation {
messages : Vec < Message >,
}
impl Conversation {
// Add a user message
pub fn add_user_message ( & mut self , text : String ) {
self . messages . push ( Message :: user ( text ));
}
// Add assistant response
pub fn add_assistant_message ( & mut self , text : String ) {
self . messages . push ( Message :: assistant ( text ));
}
// Add tool result
pub fn add_tool_result ( & mut self , tool_id : String , result : ToolResult ) {
self . messages . push ( Message :: tool_result ( tool_id , result ));
}
// Get all messages
pub fn messages ( & self ) -> & [ Message ] {
& self . messages
}
}
Message Types
pub enum MessageContent {
Text ( TextContent ), // Plain text
ToolRequest ( ToolRequest ), // Tool invocation from AI
ToolResponse ( ToolResponse ), // Tool result
Image ( ImageContent ), // Image data (vision models)
Thinking ( ThinkingContent ), // Model reasoning (if available)
}
pub struct Message {
pub role : Role , // User or Assistant
pub content : Vec < MessageContent >,
pub metadata : ProviderMetadata , // Token counts, etc.
}
Context Management
Goose automatically manages context to stay within model limits:
Context Compaction
// From crates/goose/src/context_mgmt/
const DEFAULT_COMPACTION_THRESHOLD : f64 = 0.75 ;
pub fn check_if_compaction_needed (
messages : & [ Message ],
context_limit : usize ,
) -> bool {
let token_count = count_tokens ( messages );
token_count > ( context_limit as f64 * COMPACTION_THRESHOLD ) as usize
}
pub fn compact_messages (
messages : Vec < Message >,
context_limit : usize ,
) -> Vec < Message > {
// Strategy:
// 1. Keep system prompt
// 2. Keep recent messages (last N turns)
// 3. Summarize middle section
// 4. Preserve important context (errors, key decisions)
let recent_threshold = 10 ; // Keep last 10 message pairs
let mut compacted = Vec :: new ();
// System prompt (always keep)
if let Some ( system_msg ) = messages . first () {
compacted . push ( system_msg . clone ());
}
// Middle section (summarize)
if messages . len () > recent_threshold {
let summary = summarize_messages (
& messages [ 1 .. messages . len () - recent_threshold ]
);
compacted . push ( Message :: assistant ( summary ));
}
// Recent messages (keep all)
let recent_start = messages . len () . saturating_sub ( recent_threshold );
compacted . extend_from_slice ( & messages [ recent_start .. ]);
compacted
}
Compaction is triggered automatically:
// Before sending to provider
if check_if_compaction_needed ( & conversation . messages, model_context_limit ) {
// Show user what's happening
yield AgentEvent :: Thinking ( "Compacting conversation history..." );
conversation . messages = compact_messages (
conversation . messages,
model_context_limit ,
);
}
Extension Data
Sessions store extension-specific data:
pub struct ExtensionData {
enabled_extensions : EnabledExtensionsState , // Which extensions are active
extension_state : HashMap < String , Value >, // Extension-specific data
}
Extensions can persist state across messages:
# In an MCP server
@server.tool ()
async def save_preference ( key : str , value : str ) -> list[TextContent]:
# Store in session extension data
session_state[key] = value
return [TextContent( type = "text" , text = f "Saved { key } = { value } " )]
@server.tool ()
async def get_preference ( key : str ) -> list[TextContent]:
# Retrieve from session extension data
value = session_state.get(key, "not set" )
return [TextContent( type = "text" , text = f " { key } = { value } " )]
Session Naming
Goose automatically generates descriptive session names:
// After first few messages, use AI to generate name
if conversation . messages . len () == MSG_COUNT_FOR_SESSION_NAME_GENERATION {
if ! session . user_set_name {
let name = provider . generate_session_name (
& conversation . messages
) . await ? ;
session_manager
. update_session ( & session . id)
. name ( name )
. apply ()
. await ? ;
}
}
The AI analyzes the conversation and suggests names like:
“Refactoring authentication module”
“Debugging WebSocket connection issues”
“Setting up CI/CD pipeline”
Users can override:
goose session rename abc123 "My custom name"
Token Tracking
Sessions track token usage for cost estimation:
pub struct Session {
// Current session totals
pub total_tokens : Option < i32 >,
pub input_tokens : Option < i32 >,
pub output_tokens : Option < i32 >,
// Accumulated across all time (even after compaction)
pub accumulated_total_tokens : Option < i32 >,
pub accumulated_input_tokens : Option < i32 >,
pub accumulated_output_tokens : Option < i32 >,
}
After each model call:
let usage = provider_response . usage;
session_manager
. update_session ( & session . id)
. total_tokens ( Some ( usage . total_tokens))
. input_tokens ( Some ( usage . input_tokens))
. output_tokens ( Some ( usage . output_tokens))
. accumulated_total_tokens ( Some (
session . accumulated_total_tokens . unwrap_or ( 0 ) + usage . total_tokens
))
. apply ()
. await ? ;
Session Isolation
Sessions are isolated for security and organization:
Working Directory Isolation
Each session operates in its own working directory:
// Session A
Session {
id : "abc123" ,
working_dir : "/home/user/project-a" ,
// ...
}
// Session B
Session {
id : "def456" ,
working_dir : "/home/user/project-b" ,
// ...
}
File operations are scoped to the working directory:
# Agent in session A can only access /home/user/project-a
read_file( "config.yaml" ) # Reads /home/user/project-a/config.yaml
Extension Isolation
Extensions are session-specific:
// Session A has developer + github extensions
// Session B has developer + database extensions
// They don't interfere with each other
Conversation Isolation
Conversation history doesn’t leak between sessions:
// Session A's conversation
Session A : [ "How do I authenticate?" , "Use OAuth2..." ]
// Session B's conversation (separate)
Session B : [ "Deploy to production" , "Running deployment..." ]
Multi-Session Workflows
You can work with multiple sessions simultaneously:
# Terminal 1: Work on feature A
goose session resume feature-a
# Terminal 2: Work on bugfix B (different session)
goose session resume bugfix-b
# Terminal 3: Code review (yet another session)
goose run --recipe code-review.yaml
Each session maintains independent:
Conversation history
Working directory
Extension state
Model/provider settings
Session Management API
REST API
// Create session
POST / sessions
{
"workingDirectory" : "/path/to/project" ,
"name" : "My Task" ,
"recipe" : { /* recipe object */ },
"recipeValues" : { /* parameter values */ }
}
// List sessions
GET / sessions ? type = user & limit = 10 & offset = 0
// Get session
GET / sessions / { id }
// Update session
PATCH / sessions / { id }
{
"name" : "Updated Name"
}
// Delete session
DELETE / sessions / { id }
// Get session messages
GET / sessions / { id } / messages
Agent Client Protocol (ACP)
# Create session
response = client.send_request( "session/new" , {
"cwd" : "/path/to/project" ,
"recipe" : recipe_config
})
session_id = response[ "result" ][ "sessionId" ]
# Load existing session
response = client.send_request( "session/load" , {
"sessionId" : session_id
})
# Send prompt to session
response = client.send_request( "session/prompt" , {
"sessionId" : session_id,
"prompt" : [{ "type" : "text" , "text" : "Analyze the codebase" }]
})
Session Insights
Get aggregated statistics:
pub struct SessionInsights {
pub total_sessions : usize ,
pub total_tokens : i64 ,
}
// Via API
GET / sessions / insights
{
"total_sessions" : 42 ,
"total_tokens" : 1_234_567
}
Best Practices
Use descriptive session names
# Good: Descriptive names
goose session create --name "Implement OAuth2 authentication"
goose session create --name "Debug production memory leak"
# Bad: Vague names
goose session create --name "Work"
goose session create --name "Session 1"
Set appropriate working directories
# Create session in project root
cd /path/to/my-project
goose session create
# Agent has full context of project structure
# Can access all files, run tests, etc.
# List sessions
goose session list
# Delete completed sessions
goose session delete abc123
# Or archive for later reference
goose session archive abc123
# Check token usage
goose session info abc123
# Session: Implement authentication
# Total tokens: 12,543
# Input tokens: 8,234
# Output tokens: 4,309
# Estimated cost: $0.15
Use session types appropriately
// User sessions for interactive work
SessionType :: User
// Subagent sessions for delegated tasks (auto-managed)
SessionType :: SubAgent
// Scheduled sessions for automation
SessionType :: Scheduled
Troubleshooting
Session Not Found
# List all sessions
goose session list --all
# Search by name
goose session list --search "authentication"
Session State Corruption
# Validate session
goose session validate abc123
# Repair if needed
goose session repair abc123
High Token Usage
# Enable aggressive compaction
goose session configure abc123 --compact-threshold 0.5
# Or limit conversation length
goose session configure abc123 --max-turns 20
Lost Session Data
# Sessions backed up to
ls ~/.config/goose/sessions/backups/
# Restore from backup
goose session restore --from-backup 2024-03-04-abc123.db
Next Steps
Agents Learn about agent orchestration
Recipes Configure sessions with recipes
CLI Reference Session management commands
API Reference Session management API