The RunState type represents the complete state of an agent execution. It’s returned from every run() call and can be passed back to continue conversations.
Type Definition
type RunState = {
sessionState?: SessionState
output: AgentOutput
}
Fields
Complete session state including message history, file context, and agent state. Pass this to previousRun to continue the conversation.
The agent’s output from this run. This is a discriminated union based on the type field.
Session State
The session state contains all context needed to continue a conversation.
fileContext
ProjectFileContext
required
Project files, knowledge files, agent templates, and file tree information
State of the main agent including message history and execution context
Agent State
Unique identifier for the agent (deprecated, use runId instead)
Type of agent (e.g., base, base_max, file_picker)
Array of all messages in the conversation
Number of steps the agent can still take (affected by maxAgentSteps)
Total credits used in this session
Credits used directly by this agent (excluding subagents)
Accurate token count from the LLM provider
agentContext
Record<string, Subgoal>
required
Agent’s internal context and subgoals
Array of ancestor run IDs (for nested agents)
State of any spawned subagents
Structured output from the agent
ID of the parent agent (for subagents)
System prompt used by the agent
toolDefinitions
Record<string, { description?: string; inputSchema: {} }>
required
Available tool definitions
Agent Output Types
The output field is a discriminated union with four possible types:
Structured Output
Returned when the agent produces structured data.
type
'structuredOutput'
required
Output type identifier
value
Record<string, any> | null
required
Structured data returned by the agent
Example:
{
type: 'structuredOutput',
value: {
filesCreated: ['index.ts', 'types.ts'],
linesOfCode: 145
}
}
Last Message
Returns the last turn of the conversation (assistant and tool messages).
Array of messages from the last turn, including tool results
Example:
{
type: 'lastMessage',
value: [
{
role: 'assistant',
content: [{ type: 'text', text: 'I will create the file' }]
},
{
role: 'tool',
toolName: 'write_file',
output: [{ type: 'json', value: { success: true } }]
}
]
}
All Messages
Returns the complete message history.
Complete array of all messages in the conversation
Example:
{
type: 'allMessages',
value: [
{ role: 'user', content: [{ type: 'text', text: 'Create a file' }] },
{ role: 'assistant', content: [{ type: 'text', text: 'Creating file...' }] }
]
}
Error
Returned when the agent encounters an error.
Error message describing what went wrong
HTTP status code if the error is related to an API call
Example:
{
type: 'error',
message: 'Failed to connect to API: Network timeout',
statusCode: 503
}
Continuation Pattern
Use the RunState to continue conversations:
import { CodebuffClient } from '@codebuff/sdk'
const client = new CodebuffClient({ apiKey: 'cb_xxx' })
// First run
const firstRun = await client.run({
agent: 'base',
prompt: 'Create a TypeScript file'
})
// Continue the conversation
const secondRun = await client.run({
agent: 'base',
prompt: 'Now add tests for it',
previousRun: firstRun // Pass the previous state
})
// Chain multiple runs
const thirdRun = await client.run({
agent: 'base',
prompt: 'Add documentation',
previousRun: secondRun
})
Accessing Output
const result = await client.run({
agent: 'base',
prompt: 'Create hello world'
})
if (result.output.type === 'error') {
console.error('Error:', result.output.message)
if (result.output.statusCode) {
console.error('Status code:', result.output.statusCode)
}
} else if (result.output.type === 'structuredOutput') {
console.log('Agent output:', result.output.value)
} else if (result.output.type === 'lastMessage') {
console.log('Last turn:', result.output.value)
} else if (result.output.type === 'allMessages') {
console.log('Full history:', result.output.value)
}
Inspecting State
const result = await client.run({
agent: 'base',
prompt: 'Analyze the codebase'
})
if (result.sessionState) {
console.log('Messages:', result.sessionState.mainAgentState.messageHistory.length)
console.log('Steps remaining:', result.sessionState.mainAgentState.stepsRemaining)
console.log('Credits used:', result.sessionState.mainAgentState.creditsUsed)
console.log('Token count:', result.sessionState.mainAgentState.contextTokenCount)
}
Persistence
You can serialize and persist RunState to continue sessions later:
import fs from 'fs'
// Save state
const result = await client.run({
agent: 'base',
prompt: 'Start a feature'
})
fs.writeFileSync('session.json', JSON.stringify(result))
// Load and continue
const savedState = JSON.parse(fs.readFileSync('session.json', 'utf8'))
const continuedRun = await client.run({
agent: 'base',
prompt: 'Continue the feature',
previousRun: savedState
})
State Overrides
You can override certain fields when continuing:
const secondRun = await client.run({
agent: 'base',
prompt: 'Continue',
previousRun: firstRun,
maxAgentSteps: 50, // Override step limit
projectFiles: newFiles, // Update project files
knowledgeFiles: newKnowledge // Update knowledge
})
These overrides are applied via applyOverridesToSessionState() which:
- Deep clones the base session state
- Updates specified fields
- Recomputes derived data (file tree, token scores) when needed
- Merges agent definitions and custom tools