Overview
ADK-TS provides multiple code execution environments for running Python code generated by LLMs. From unsafe local execution for development to secure container-based and cloud execution for production, you can choose the right environment for your needs.
BaseCodeExecutor
All code executors extend BaseCodeExecutor:
import { BaseCodeExecutor } from '@iqai/adk' ;
import type { CodeExecutionInput , CodeExecutionResult } from '@iqai/adk' ;
abstract class BaseCodeExecutor {
abstract executeCode (
invocationContext : InvocationContext ,
codeExecutionInput : CodeExecutionInput ,
) : Promise < CodeExecutionResult >;
}
Source: packages/adk/src/code-executors/base-code-executor.ts:44
Configuration Options
interface BaseCodeExecutorConfig {
// Extract data files from model request
optimizeDataFile ?: boolean ;
// Maintain state between executions
stateful ?: boolean ;
// Retry attempts on errors
errorRetryAttempts ?: number ;
// Code block delimiters
codeBlockDelimiters ?: Array <[ string , string ]>;
// Result formatting
executionResultDelimiters ?: [ string , string ];
}
Built-in Executors
UnsafeLocalCodeExecutor
Development Only : This executor runs Python code directly on your machine without sandboxing. Never use in production or with untrusted code.
Executes code using the local Python interpreter:
import { UnsafeLocalCodeExecutor } from '@iqai/adk' ;
const executor = new UnsafeLocalCodeExecutor ({
stateful: true , // Maintain variables between executions
errorRetryAttempts: 2 , // Retry on errors
optimizeDataFile: false ,
});
// Execute code
const result = await executor . executeCode ( context , {
code: `
import math
result = math.sqrt(16)
print(f"Square root: {result}")
` ,
});
console . log ( result . stdout ); // "Square root: 4.0"
Use Cases:
Local development
Rapid prototyping
Testing code generation
Limitations:
No sandboxing
Security risk with untrusted code
Requires Python installed locally
ContainerCodeExecutor
Executes code in isolated Docker containers for security:
import { ContainerCodeExecutor } from '@iqai/adk' ;
const executor = new ContainerCodeExecutor ({
// Option 1: Use pre-built image
image: 'python:3.11-slim' ,
// Option 2: Build from Dockerfile
// dockerPath: './docker/python-executor',
executionTimeout: 30000 , // 30 second timeout
});
const result = await executor . executeCode ( context , {
code: `
import pandas as pd
import numpy as np
data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
df = pd.DataFrame(data)
print(df.describe())
` ,
});
Source: packages/adk/src/code-executors/container-code-executor.ts:52
Features
✅ Isolated Execution : Each execution runs in a separate container
✅ Timeout Control : Prevent infinite loops
✅ Custom Images : Bring your own dependencies
✅ Production Ready : Secure by design
Docker Configuration
Basic Usage
Custom Image
Build from Dockerfile
const executor = new ContainerCodeExecutor ({
image: 'python:3.11-slim' ,
executionTimeout: 30000 ,
});
Dockerfile Example
# docker/python-executor/Dockerfile
FROM python:3.11-slim
RUN pip install --no-cache-dir \
pandas \
numpy \
matplotlib \
scipy \
scikit-learn
WORKDIR /workspace
Container Lifecycle
const executor = new ContainerCodeExecutor ({ image: 'python:3.11' });
// Container starts on first execution
await executor . executeCode ( context , { code: '...' });
// Reuses container for subsequent calls
await executor . executeCode ( context , { code: '...' });
// Clean up manually if needed
await executor . dispose ();
ContainerCodeExecutor automatically cleans up containers on process exit.
VertexAICodeExecutor
Executes code using Google Cloud’s Vertex AI Code Interpreter:
import { VertexAICodeExecutor } from '@iqai/adk' ;
const executor = new VertexAICodeExecutor ({
projectId: 'my-gcp-project' ,
location: 'us-central1' ,
});
const result = await executor . executeCode ( context , {
code: `
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave')
plt.savefig('sine.png')
print('Plot saved')
` ,
});
// Access output files
if ( result . outputFiles ?. length > 0 ) {
console . log ( 'Generated files:' , result . outputFiles );
}
Features:
✅ Managed Infrastructure : No container management
✅ Scalable : Handles concurrent executions
✅ File Support : Generate and retrieve output files
✅ Pre-installed Libraries : NumPy, Pandas, Matplotlib, etc.
Requirements:
Google Cloud project with Vertex AI enabled
Application Default Credentials configured
Vertex AI API permissions
Using with Agents
Code Execution Agent
import { AgentBuilder , ContainerCodeExecutor } from '@iqai/adk' ;
const executor = new ContainerCodeExecutor ({
image: 'python:3.11-slim' ,
});
const agent = new AgentBuilder ()
. withName ( 'DataAnalyst' )
. withModel ( 'gpt-4' )
. withCodeExecutor ( executor )
. withInstruction ( `
You are a data analysis assistant.
Use Python code to analyze data and generate insights.
You can use pandas, numpy, and matplotlib.
` )
. buildLlm ();
const response = await agent . ask (
'Analyze the correlation between temperature and ice cream sales in this dataset: [data]'
);
With Code Execution Flow
import { CodeExecutionFlow } from '@iqai/adk' ;
const flow = new CodeExecutionFlow ({
codeExecutor: new ContainerCodeExecutor ({
image: 'python:3.11-slim' ,
}),
});
const agent = new AgentBuilder ()
. withModel ( 'claude-sonnet-4' )
. withFlow ( flow )
. buildLlm ();
Source: packages/adk/src/flows/llm-flows/code-execution.ts
Code Execution Results
interface CodeExecutionResult {
stdout : string ; // Standard output
stderr : string ; // Error output
outputFiles : Array <{ // Generated files (if any)
name : string ;
content : Buffer ;
mimeType : string ;
}>;
}
const result = await executor . executeCode ( context , { code });
if ( result . stderr ) {
console . error ( 'Execution error:' , result . stderr );
}
if ( result . outputFiles . length > 0 ) {
for ( const file of result . outputFiles ) {
console . log ( `Generated ${ file . name } ( ${ file . mimeType } )` );
// Save or process the file
}
}
Error Handling
Retry Logic
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
errorRetryAttempts: 3 , // Retry up to 3 times
});
try {
const result = await executor . executeCode ( context , { code });
if ( result . stderr && result . stderr . includes ( 'Error' )) {
// Handle execution errors
console . error ( 'Code execution failed:' , result . stderr );
}
} catch ( error ) {
// Handle executor errors (timeout, container failure, etc.)
console . error ( 'Executor error:' , error );
}
Timeout Handling
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
executionTimeout: 10000 , // 10 seconds
});
const result = await executor . executeCode ( context , { code });
if ( result . stderr ?. includes ( 'timeout' )) {
console . log ( 'Execution timed out - consider increasing limit' );
}
Security Best Practices
Production Guidelines:
⛔ Never use UnsafeLocalCodeExecutor in production
✅ Always use containerized or cloud executors
✅ Set reasonable execution timeouts
✅ Limit resource usage (CPU, memory)
✅ Validate generated code before execution
✅ Monitor execution patterns for abuse
Resource Limits
// Docker resource constraints
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
executionTimeout: 30000 ,
// These would need custom implementation:
// maxMemory: '512M',
// maxCpu: '0.5',
});
Code Validation
import { BaseLlmRequestProcessor } from '@iqai/adk' ;
class CodeValidationProcessor extends BaseLlmRequestProcessor {
async * runAsync ( ctx , request ) {
// Inspect generated code before execution
const code = this . extractCode ( request );
if ( this . containsDangerousOperations ( code )) {
throw new Error ( 'Code contains forbidden operations' );
}
}
private containsDangerousOperations ( code : string ) : boolean {
const forbidden = [
'os.system' ,
'subprocess' ,
'eval(' ,
'exec(' ,
'__import__' ,
];
return forbidden . some ( op => code . includes ( op ));
}
}
Advanced Patterns
Stateful Execution
const executor = new UnsafeLocalCodeExecutor ({
stateful: true , // Maintain variables between calls
});
// First execution
await executor . executeCode ( context , {
code: 'x = 10; y = 20' ,
});
// Second execution - variables persist
const result = await executor . executeCode ( context , {
code: 'print(x + y)' ,
});
console . log ( result . stdout ); // "30"
Data File Optimization
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
optimizeDataFile: true , // Extract CSV files from request
});
// The executor will detect and extract data files
// from the LLM request and make them available
// to the code execution environment
Custom Code Delimiters
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
codeBlockDelimiters: [
[ '```python \n ' , ' \n ```' ],
[ '<code> \n ' , ' \n </code>' ],
],
executionResultDelimiters: [ '<output> \n ' , ' \n </output>' ],
});
Container Warmup : First execution is slower (container startup)
Reuse Containers : Keep executors alive for multiple executions
Parallel Execution : Multiple ContainerCodeExecutor instances run concurrently
Cleanup : Dispose executors when done to free resources
// Good: Reuse executor
const executor = new ContainerCodeExecutor ({ image: 'python:3.11' });
for ( const task of tasks ) {
await executor . executeCode ( context , { code: task . code });
}
await executor . dispose ();
// Avoid: Creating new executor for each execution
for ( const task of tasks ) {
const executor = new ContainerCodeExecutor ({ image: 'python:3.11' });
await executor . executeCode ( context , { code: task . code });
await executor . dispose ();
}
Monitoring and Debugging
import { Logger } from '@iqai/adk' ;
const logger = new Logger ({ name: 'CodeExecutor' });
const executor = new ContainerCodeExecutor ({
image: 'python:3.11' ,
});
const result = await executor . executeCode ( context , { code });
logger . debug ( 'Execution complete' , {
exitCode: result . exitCode ,
stdoutLength: result . stdout . length ,
stderrLength: result . stderr . length ,
outputFiles: result . outputFiles . length ,
});
Next Steps
Streaming Stream responses in real-time with Events
Authentication Secure tool access with auth patterns