Documentation
¶
Overview ¶
Package codeexecutor provides secure code execution with multiple backends and safety controls.
The codeexecutor package implements the types.CodeExecutor interface with three distinct execution backends, each offering different levels of security and functionality for running code generated by agents or provided by users.
Execution Backends ¶
The package provides three execution strategies:
- BuiltInExecutor: Uses model's native code execution (Gemini 2.0+)
- ContainerExecutor: Docker-based sandboxing with resource limits
- LocalExecutor: Direct host execution (requires explicit opt-in)
Security Model ¶
Execution backends are ordered by security level:
- BuiltInExecutor: Safest - Uses model's built-in sandboxed execution
- ContainerExecutor: Secure - Docker isolation with network restrictions
- LocalExecutor: Unsafe - Direct host execution (development only)
The choice of executor depends on security requirements and available infrastructure.
Basic Usage ¶
Creating executors:
// Built-in executor (safest) executor := codeexecutor.NewBuiltInExecutor() // Container executor (secure) executor, err := codeexecutor.NewContainerExecutor( codeexecutor.WithImage("python:3.11-slim"), codeexecutor.WithTimeout(30*time.Second), ) // Local executor (unsafe - requires explicit opt-in) executor := codeexecutor.NewLocalExecutor( codeexecutor.WithAllowUnsafe(true), codeexecutor.WithWorkDir("/tmp/code-execution"), )
Executing code:
input := &types.CodeExecutionInput{ Code: "print('Hello, World!')", Language: "python", } result, err := executor.ExecuteCode(ctx, invocationContext, input) if err != nil { log.Fatal(err) } fmt.Println("Output:", result.Output) fmt.Println("Exit Code:", result.ExitCode)
Execution Features ¶
Stateful Execution:
- Variables and imports persist across Execute calls
- Useful for iterative development and data analysis
- Configurable via execution options
Long-Running Operations:
- Support for operations that take extended time
- Proper timeout and cancellation handling
- Progress reporting capabilities
Data File Optimization:
- Automatic extraction and processing of CSV and data files
- Direct file attachment to execution environment
- Optimized for large datasets
Configuration Options ¶
Executors support extensive configuration:
executor := codeexecutor.NewContainerExecutor( codeexecutor.WithStateful(true), // Enable stateful execution codeexecutor.WithLongRunning(true), // Support long operations codeexecutor.WithOptimizeDataFiles(true), // Optimize data file handling codeexecutor.WithMaxRetries(3), // Retry failed executions codeexecutor.WithRetryDelay(time.Second), // Delay between retries codeexecutor.WithTimeout(60*time.Second), // Execution timeout )
Language Support ¶
The package supports multiple programming languages:
- Python (most common for AI/ML tasks)
- JavaScript/Node.js
- R (data analysis)
- Bash/Shell scripts
- Custom language support via container images
Language detection is automatic based on code patterns and explicit hints.
Container Execution ¶
ContainerExecutor provides robust sandboxing:
executor, err := codeexecutor.NewContainerExecutor( codeexecutor.WithImage("python:3.11-slim"), codeexecutor.WithMemoryLimit("512m"), codeexecutor.WithCPULimit("1.0"), codeexecutor.WithNetworkDisabled(true), codeexecutor.WithTimeout(30*time.Second), )
Features:
- Resource limits (memory, CPU, disk)
- Network isolation
- Filesystem sandboxing
- Custom Docker images
- Automatic cleanup
Error Handling and Retries ¶
Robust error handling with configurable retry logic:
// Execution errors are automatically retried result, err := executor.ExecuteCode(ctx, ictx, input) if err != nil { // Check if retries were exhausted if execErr, ok := err.(*types.ExecutionError); ok { fmt.Printf("Failed after %d attempts\n", execErr.Attempts) } }
Integration with Agents ¶
Code executors integrate seamlessly with the agent system:
agent := agent.NewLLMAgent(ctx, "coder", agent.WithCodeExecutor(executor), agent.WithInstruction("You can execute code to solve problems"), )
Agents automatically:
- Extract code blocks from responses
- Execute code using the configured executor
- Include execution results in conversation context
- Handle errors and retries transparently
Thread Safety ¶
All executors are safe for concurrent use. However, stateful executors maintain per-session state, so concurrent executions within the same session may interfere with each other.
Resource Management ¶
Proper resource cleanup is essential:
defer executor.Close() // Always close executors
Executors manage:
- Docker containers and images
- Temporary files and directories
- Network connections
- Background processes
Best Practices ¶
- Use BuiltInExecutor when supported by the model
- Use ContainerExecutor for production deployments
- Never use LocalExecutor in production
- Always set appropriate timeouts
- Configure resource limits for containers
- Handle errors and retries appropriately
- Close executors when done
Index ¶
- Constants
- type BuiltInExecutor
- func (e *BuiltInExecutor) Close() error
- func (e *BuiltInExecutor) CodeBlockDelimiters() []types.DelimiterPair
- func (e *BuiltInExecutor) ErrorRetryAttempts() int
- func (e *BuiltInExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, ...) (*types.CodeExecutionResult, error)
- func (e *BuiltInExecutor) ExecutionResultDelimiters() types.DelimiterPair
- func (e *BuiltInExecutor) IsLongRunning() bool
- func (e *BuiltInExecutor) IsStateful() bool
- func (e *BuiltInExecutor) OptimizeDataFile() bool
- func (a *BuiltInExecutor) ProcessLLMRequest(ctx context.Context, request *types.LLMRequest)
- type CodeBlock
- type CodeBlockParser
- type CodeExecutionUtils
- func (e *CodeExecutionUtils) BuildCodeExecutionResultPart(codeExecutionResult *types.CodeExecutionResult) *genai.Part
- func (e *CodeExecutionUtils) BuildExecutableCodePart(code string) *genai.Part
- func (e *CodeExecutionUtils) ConvertCodeExecutionParts(content *genai.Content, ...)
- func (e *CodeExecutionUtils) ExtractCodeAndTruncateContent(content *genai.Content, codeBlockDelimiters []types.DelimiterPair) string
- func (e *CodeExecutionUtils) GetEncodedFileContent(data []byte) []byte
- type CodeExecutorContext
- func (ec *CodeExecutorContext) AddExecutionResult(result *types.CodeExecutionResult)
- func (ec *CodeExecutorContext) AddInputFiles(files ...*types.CodeExecutionFile)
- func (ec *CodeExecutorContext) AddProcessedFileNames(fileNames ...string)
- func (ec *CodeExecutorContext) ClearInputFiles(files ...*types.CodeExecutionFile)
- func (ec *CodeExecutorContext) GetErrorCount(invocationID string) int
- func (ec *CodeExecutorContext) GetExecutionID() string
- func (ec *CodeExecutorContext) GetInputFiles() []*types.CodeExecutionFile
- func (ec *CodeExecutorContext) GetProcessedFileNames() []string
- func (ec *CodeExecutorContext) GetStateDelta() map[string]any
- func (ec *CodeExecutorContext) IncrementErrorCount(invocationID string)
- func (ec *CodeExecutorContext) ResetErrorCount(invocationID string)
- func (ec *CodeExecutorContext) SetExecutionID(executionID string)
- func (ec *CodeExecutorContext) UpdateExecutionResult(invocationID, code, stdout, stderr string)
- type ContainerExecutor
- func (e *ContainerExecutor) Close() error
- func (e *ContainerExecutor) CodeBlockDelimiters() []types.DelimiterPair
- func (e *ContainerExecutor) ErrorRetryAttempts() int
- func (e *ContainerExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, ...) (*types.CodeExecutionResult, error)
- func (e *ContainerExecutor) ExecutionResultDelimiters() types.DelimiterPair
- func (e *ContainerExecutor) IsLongRunning() bool
- func (e *ContainerExecutor) IsStateful() bool
- func (e *ContainerExecutor) OptimizeDataFile() bool
- type ContainerExecutorOption
- func WithCPULimit(limit int64) ContainerExecutorOption
- func WithDockerClient(client *client.Client) ContainerExecutorOption
- func WithDockerImage(dockerImage string) ContainerExecutorOption
- func WithDockerfile(dockerfile string) ContainerExecutorOption
- func WithMemoryLimit(limit int64) ContainerExecutorOption
- type ExecutionResultFormatter
- type LocalExecutor
- func (e *LocalExecutor) Close() error
- func (e *LocalExecutor) CodeBlockDelimiters() []types.DelimiterPair
- func (e *LocalExecutor) ErrorRetryAttempts() int
- func (e *LocalExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, ...) (*types.CodeExecutionResult, error)
- func (e *LocalExecutor) ExecutionResultDelimiters() types.DelimiterPair
- func (e *LocalExecutor) IsLongRunning() bool
- func (e *LocalExecutor) IsStateful() bool
- func (e *LocalExecutor) OptimizeDataFile() bool
- type LocalExecutorOption
Constants ¶
const ( ContextKey = "_code_execution_context" SessionIDKey = "execution_session_id" ProcessedFileNamesKey = "processed_input_files" InputFileKey = "_code_executor_input_files" ErrorCountKey = "_code_executor_error_counts" CodeExecutionResultsKey = "_code_execution_results" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BuiltInExecutor ¶
type BuiltInExecutor struct {
// contains filtered or unexported fields
}
BuiltInExecutor uses the model's built-in code execution capabilities. This is supported by Gemini 2.0+ models with native code execution tools.
func NewBuiltInExecutor ¶
func NewBuiltInExecutor(opts ...types.ExecutionOption) *BuiltInExecutor
NewBuiltInExecutor creates a new built-in executor using the model's native capabilities.
func (*BuiltInExecutor) Close ¶
func (e *BuiltInExecutor) Close() error
Close implements types.CodeExecutor.
func (*BuiltInExecutor) CodeBlockDelimiters ¶
func (e *BuiltInExecutor) CodeBlockDelimiters() []types.DelimiterPair
CodeBlockDelimiters implements types.CodeExecutor.
func (*BuiltInExecutor) ErrorRetryAttempts ¶
func (e *BuiltInExecutor) ErrorRetryAttempts() int
ErrorRetryAttempts implements types.CodeExecutor.
func (*BuiltInExecutor) ExecuteCode ¶
func (e *BuiltInExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, input *types.CodeExecutionInput) (*types.CodeExecutionResult, error)
ExecuteCode implements types.CodeExecutor.
func (*BuiltInExecutor) ExecutionResultDelimiters ¶
func (e *BuiltInExecutor) ExecutionResultDelimiters() types.DelimiterPair
ExecutionResultDelimiters implements types.CodeExecutor.
func (*BuiltInExecutor) IsLongRunning ¶
func (e *BuiltInExecutor) IsLongRunning() bool
IsLongRunning implements types.CodeExecutor.
func (*BuiltInExecutor) IsStateful ¶
func (e *BuiltInExecutor) IsStateful() bool
IsStateful implements types.CodeExecutor.
func (*BuiltInExecutor) OptimizeDataFile ¶
func (e *BuiltInExecutor) OptimizeDataFile() bool
OptimizeDataFile implements types.CodeExecutor.
func (*BuiltInExecutor) ProcessLLMRequest ¶
func (a *BuiltInExecutor) ProcessLLMRequest(ctx context.Context, request *types.LLMRequest)
ProcessLLMRequest processes the LLM request to ensure it has the necessary configuration for code execution.
type CodeBlock ¶
type CodeBlock struct { Language string Code string Start int // Starting position in original text End int // Ending position in original text }
CodeBlock represents a parsed code block with language and content.
type CodeBlockParser ¶
type CodeBlockParser struct {
// contains filtered or unexported fields
}
CodeBlockParser extracts code blocks from text using configurable delimiters.
func NewCodeBlockParser ¶
func NewCodeBlockParser(delimiters []types.DelimiterPair) *CodeBlockParser
NewCodeBlockParser creates a new parser with the given delimiters.
func NewDefaultCodeBlockParser ¶
func NewDefaultCodeBlockParser() *CodeBlockParser
NewDefaultCodeBlockParser creates a parser with default delimiters.
func (*CodeBlockParser) ExtractCodeBlocks ¶
func (p *CodeBlockParser) ExtractCodeBlocks(text string) ([]*CodeBlock, error)
ExtractCodeBlocks extracts all code blocks from the given text.
func (*CodeBlockParser) FilterByLanguage ¶
func (p *CodeBlockParser) FilterByLanguage(blocks []*CodeBlock, languages ...string) []*CodeBlock
FilterByLanguage returns only code blocks matching the specified languages. If no languages are specified, all blocks are returned.
type CodeExecutionUtils ¶
type CodeExecutionUtils struct{}
CodeExecutionUtils represents an utility functions for code execution.
func NewCodeExecutionUtils ¶
func NewCodeExecutionUtils() *CodeExecutionUtils
NewCodeExecutionUtils creates a new instance of CodeExecutionUtils.
func (*CodeExecutionUtils) BuildCodeExecutionResultPart ¶
func (e *CodeExecutionUtils) BuildCodeExecutionResultPart(codeExecutionResult *types.CodeExecutionResult) *genai.Part
BuildCodeExecutionResultPart builds the code execution result part from the code execution result.
func (*CodeExecutionUtils) BuildExecutableCodePart ¶
func (e *CodeExecutionUtils) BuildExecutableCodePart(code string) *genai.Part
BuildExecutableCodePart builds an executable code part with code string.
func (*CodeExecutionUtils) ConvertCodeExecutionParts ¶
func (e *CodeExecutionUtils) ConvertCodeExecutionParts(content *genai.Content, codeBlockDelimiter, executionResultDelimiters types.DelimiterPair)
ConvertCodeExecutionParts converts the code execution parts to text parts in a *genai.Content.
func (*CodeExecutionUtils) ExtractCodeAndTruncateContent ¶
func (e *CodeExecutionUtils) ExtractCodeAndTruncateContent(content *genai.Content, codeBlockDelimiters []types.DelimiterPair) string
ExtractCodeAndTruncateContent extracts the first code block from the content and truncate everything after it.
func (*CodeExecutionUtils) GetEncodedFileContent ¶
func (e *CodeExecutionUtils) GetEncodedFileContent(data []byte) []byte
GetEncodedFileContent gets the file content as a base64-encoded bytes.
type CodeExecutorContext ¶
type CodeExecutorContext struct {
// contains filtered or unexported fields
}
CodeExecutorContext manages persistent state for code execution sessions. It tracks execution history, error counts, and file management across multiple execution calls.
func GetContextFromInvocation ¶
func GetContextFromInvocation(ictx *types.InvocationContext, executionID string) *CodeExecutorContext
GetContextFromInvocation extracts or creates a CodeExecutorContext from an InvocationContext. This enables isolated code execution state management per invocation while maintaining session-level persistence across multiple execution calls.
The function creates a State object from the session's state map and uses the provided execution ID for context isolation. If executionID is empty, it falls back to the invocation ID from the context.
Returns nil if the invocation context or its session is nil.
func NewExecutionContext ¶
func NewExecutionContext(sessionState *types.State) *CodeExecutorContext
NewExecutionContext creates a new execution context with the given execution ID.
func (*CodeExecutorContext) AddExecutionResult ¶
func (ec *CodeExecutorContext) AddExecutionResult(result *types.CodeExecutionResult)
AddExecutionResult adds an execution result to the context. This is a convenience method that extracts the execution details from the result.
func (*CodeExecutorContext) AddInputFiles ¶
func (ec *CodeExecutorContext) AddInputFiles(files ...*types.CodeExecutionFile)
AddInputFiles adds files to the input files list.
func (*CodeExecutorContext) AddProcessedFileNames ¶
func (ec *CodeExecutorContext) AddProcessedFileNames(fileNames ...string)
AddProcessedFileNames adds file names to the processed files list.
func (*CodeExecutorContext) ClearInputFiles ¶
func (ec *CodeExecutorContext) ClearInputFiles(files ...*types.CodeExecutionFile)
ClearInputFiles removes the input files and processed file names to the code executor context.
func (*CodeExecutorContext) GetErrorCount ¶
func (ec *CodeExecutorContext) GetErrorCount(invocationID string) int
GetErrorCount returns the error count for the given invocation ID.
func (*CodeExecutorContext) GetExecutionID ¶
func (ec *CodeExecutorContext) GetExecutionID() string
GetExecutionID returns the execution ID for this context.
func (*CodeExecutorContext) GetInputFiles ¶
func (ec *CodeExecutorContext) GetInputFiles() []*types.CodeExecutionFile
GetInputFiles returns a copy of the input files.
func (*CodeExecutorContext) GetProcessedFileNames ¶
func (ec *CodeExecutorContext) GetProcessedFileNames() []string
GetProcessedFileNames returns a copy of the processed file names.
func (*CodeExecutorContext) GetStateDelta ¶
func (ec *CodeExecutorContext) GetStateDelta() map[string]any
GetStateDelta gets the state delta to update in the persistent session state.
func (*CodeExecutorContext) IncrementErrorCount ¶
func (ec *CodeExecutorContext) IncrementErrorCount(invocationID string)
IncrementErrorCount increments the error count for the given invocation ID.
func (*CodeExecutorContext) ResetErrorCount ¶
func (ec *CodeExecutorContext) ResetErrorCount(invocationID string)
ResetErrorCount resets the error count from the session state.
func (*CodeExecutorContext) SetExecutionID ¶
func (ec *CodeExecutorContext) SetExecutionID(executionID string)
SetExecutionID updates the execution ID for this context.
func (*CodeExecutorContext) UpdateExecutionResult ¶
func (ec *CodeExecutorContext) UpdateExecutionResult(invocationID, code, stdout, stderr string)
UpdateExecutionResult updates the execution result for the given invocation ID. If the result doesn't exist, it will be added.
type ContainerExecutor ¶
type ContainerExecutor struct {
// contains filtered or unexported fields
}
ContainerExecutor represents a code executor that uses a custom container to execute code.
This provides a safer execution environment compared to local execution.
func NewContainerExecutor ¶
func NewContainerExecutor(opts ...any) (*ContainerExecutor, error)
NewContainerExecutor creates a new container-based code executor.
func (*ContainerExecutor) Close ¶
func (e *ContainerExecutor) Close() error
Close implements types.CodeExecutor.
func (*ContainerExecutor) CodeBlockDelimiters ¶
func (e *ContainerExecutor) CodeBlockDelimiters() []types.DelimiterPair
CodeBlockDelimiters implements types.CodeExecutor.
func (*ContainerExecutor) ErrorRetryAttempts ¶
func (e *ContainerExecutor) ErrorRetryAttempts() int
ErrorRetryAttempts implements types.CodeExecutor.
func (*ContainerExecutor) ExecuteCode ¶
func (e *ContainerExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, input *types.CodeExecutionInput) (*types.CodeExecutionResult, error)
ExecuteCode implements types.CodeExecutor.
func (*ContainerExecutor) ExecutionResultDelimiters ¶
func (e *ContainerExecutor) ExecutionResultDelimiters() types.DelimiterPair
ExecutionResultDelimiters implements types.CodeExecutor.
func (*ContainerExecutor) IsLongRunning ¶
func (e *ContainerExecutor) IsLongRunning() bool
IsLongRunning implements types.CodeExecutor.
func (*ContainerExecutor) IsStateful ¶
func (e *ContainerExecutor) IsStateful() bool
IsStateful implements types.CodeExecutor.
func (*ContainerExecutor) OptimizeDataFile ¶
func (e *ContainerExecutor) OptimizeDataFile() bool
OptimizeDataFile implements types.CodeExecutor.
type ContainerExecutorOption ¶
type ContainerExecutorOption func(*ContainerExecutor)
ContainerExecutorOption is a functional option for configuring ContainerExecutor.
func WithCPULimit ¶
func WithCPULimit(limit int64) ContainerExecutorOption
WithCPULimit sets the CPU limit for containers (in nano CPUs).
func WithDockerClient ¶
func WithDockerClient(client *client.Client) ContainerExecutorOption
WithDockerClient sets a custom Docker client.
func WithDockerImage ¶
func WithDockerImage(dockerImage string) ContainerExecutorOption
WithDockerImage sets the Docker image to use for execution.
func WithDockerfile ¶
func WithDockerfile(dockerfile string) ContainerExecutorOption
WithDockerfile sets the Dockerfile to use for execution.
func WithMemoryLimit ¶
func WithMemoryLimit(limit int64) ContainerExecutorOption
WithMemoryLimit sets the memory limit for containers (in bytes).
type ExecutionResultFormatter ¶
type ExecutionResultFormatter struct {
// contains filtered or unexported fields
}
ExecutionResultFormatter formats execution results with configurable delimiters.
func NewDefaultExecutionResultFormatter ¶
func NewDefaultExecutionResultFormatter() *ExecutionResultFormatter
NewDefaultExecutionResultFormatter creates a formatter with default delimiters.
func NewExecutionResultFormatter ¶
func NewExecutionResultFormatter(delimiters types.DelimiterPair) *ExecutionResultFormatter
NewExecutionResultFormatter creates a new formatter with the given delimiters.
func (*ExecutionResultFormatter) ExtractExecutionResults ¶
func (f *ExecutionResultFormatter) ExtractExecutionResults(text string) ([]string, error)
ExtractExecutionResults extracts execution results from formatted text.
func (*ExecutionResultFormatter) FormatInlineResult ¶
func (f *ExecutionResultFormatter) FormatInlineResult(result *types.CodeExecutionResult) string
FormatInlineResult formats a short inline result without delimiters.
func (*ExecutionResultFormatter) FormatResult ¶
func (f *ExecutionResultFormatter) FormatResult(result *types.CodeExecutionResult) string
FormatResult formats an execution result with delimiters.
type LocalExecutor ¶
type LocalExecutor struct {
// contains filtered or unexported fields
}
LocalExecutor executes code in the local environment.
WARNING: This executor is inherently unsafe as it runs arbitrary code with the same privileges as the calling process. Use only in trusted environments.
func NewLocalExecutor ¶
func NewLocalExecutor(opts ...any) (*LocalExecutor, error)
NewLocalExecutor creates a new local code executor.
NOTE(adk-go): This executor requires explicit opt-in to unsafe execution.
func (*LocalExecutor) Close ¶
func (e *LocalExecutor) Close() error
Close implements types.CodeExecutor.
func (*LocalExecutor) CodeBlockDelimiters ¶
func (e *LocalExecutor) CodeBlockDelimiters() []types.DelimiterPair
CodeBlockDelimiters implements types.CodeExecutor.
func (*LocalExecutor) ErrorRetryAttempts ¶
func (e *LocalExecutor) ErrorRetryAttempts() int
ErrorRetryAttempts implements types.CodeExecutor.
func (*LocalExecutor) ExecuteCode ¶
func (e *LocalExecutor) ExecuteCode(ctx context.Context, ictx *types.InvocationContext, input *types.CodeExecutionInput) (*types.CodeExecutionResult, error)
ExecuteCode implements types.CodeExecutor.
func (*LocalExecutor) ExecutionResultDelimiters ¶
func (e *LocalExecutor) ExecutionResultDelimiters() types.DelimiterPair
ExecutionResultDelimiters implements types.CodeExecutor.
func (*LocalExecutor) IsLongRunning ¶
func (e *LocalExecutor) IsLongRunning() bool
IsLongRunning implements types.CodeExecutor.
func (*LocalExecutor) IsStateful ¶
func (e *LocalExecutor) IsStateful() bool
IsStateful implements types.CodeExecutor.
func (*LocalExecutor) OptimizeDataFile ¶
func (e *LocalExecutor) OptimizeDataFile() bool
OptimizeDataFile implements types.CodeExecutor.
type LocalExecutorOption ¶
type LocalExecutorOption func(*LocalExecutor)
LocalExecutorOption is a functional option for configuring LocalExecutor.
func WithAllowUnsafe ¶
func WithAllowUnsafe(allow bool) LocalExecutorOption
WithAllowUnsafe explicitly enables unsafe local execution. This is required to use the LocalExecutor due to security implications.
func WithStateful ¶
func WithStateful(stateful bool) LocalExecutorOption
WithStateful enables stateful execution mode where variables persist between calls.
func WithWorkDir ¶
func WithWorkDir(dir string) LocalExecutorOption
WithWorkDir sets a specific working directory for code execution.