from onprem.pipelines import AgentExecutorThis notebook demonstrates how to use the Agent pipeline from OnPrem.LLM to create autonomous agents that can execute complex tasks using a variety of tools.
The pipeline works with any LiteLLM-supported model that supports tool-calling:
- Cloud: openai/gpt-5.2-codex, anthropic/claude-sonnet-4-5, gemini/gemini-1.5-pro
- Local: Ollama (ollama/llama3.1), vLLM (hosted_vllm/
), llama.cpp (use OpenAI interface)
For llama.cpp: Use openai/<model_name> (e.g., gpt-oss-120b) as model parameter and then set env variable OPENAI_API_BASE=http://localhost:<port>/v1
The AgentExecutor
The AgentExecutor allows you to launch AI agents to solve various tasks using both cloud and local models. We will use anthropic/claude-sonnet-4-5 (cloud) and glm-4.7-flash (local) for these examples.
By default, the AgentExecutor has access to 9 built-in tools. You remove access to built-in-tools as necessary. You can optionally give the agent access to custom tools, as we’ll illustrate below.
The AgentExecutor is implemented using our coding agent, PatchPal, which you’ll need to install: pip install patchpal.
AgentExecutor.print_default_tools()======================================================================
AgentExecutor Default Tools
======================================================================
These tools are used by default when enabled_tools=None:
1. read_file - Read complete file contents
2. read_lines - Read specific line ranges from files
3. edit_file - Edit files via find/replace
4. write_file - Write complete file contents
5. grep - Search for patterns in files
6. find - Find files by glob pattern
7. run_shell - Execute shell commands
8. web_search - Search the web for information
9. web_fetch - Fetch and read content from URLs
======================================================================
Customization Examples:
======================================================================
# Use defaults (all tools including shell):
executor = AgentExecutor(model='anthropic/claude-sonnet-4-5')
# Defaults but no shell access (safer):
executor = AgentExecutor(
model='openai/gpt-5-mini',
disable_shell=True
)
# Minimal tools:
executor = AgentExecutor(
model='openai/gpt-5-mini',
enabled_tools=['read_file', 'write_file']
)
# Web research only:
executor = AgentExecutor(
model='openai/gpt-5-mini',
enabled_tools=['web_search', 'web_fetch']
)
Examples
Let’s run through some examples for different scenarios.
Basic Calculator Example
In this introductory example, we will launch an agent to build a calculator module in Python.
By default, the agent will operate within the working_directory you specify (or the current folder if not working directory is specified). The agent cannot read or write outside the working directory.
Important Note:: If the agent has access to the run_shell tool, it can potentially read or modify files outside of the working directory (e.g., auto-generating and executing a Python script that writes files outside of working directory). For these reasons, you can either supply the disable_shell=True to remove shell access or sandbox=True, which runs the agent in an ephemeral container.
In this first example, we set sandbox=True. The example was run on Windows Subsystem for Linux (WSL) with PodMan installed. We will cover sandboxed execution in more detail later.
executor = AgentExecutor(
model='anthropic/claude-sonnet-4-5', # assumes ANTHROPIC_API_KEY is already set as environment variable
sandbox=True,
)
result = executor.run(
task="""
Create a simple Python calculator module with the following:
- calculator.py with add, subtract, multiply, divide functions
- test_calculator.py with pytest tests
- All tests must pass
""",
working_dir='./calculator_project'
)
print(result)time="2026-03-17T16:42:53-04:00" level=warning msg="The cgroupv2 manager is set to systemd but there is no systemd user session available"
time="2026-03-17T16:42:53-04:00" level=warning msg="For using systemd, you may need to login using an user session"
time="2026-03-17T16:42:53-04:00" level=warning msg="Alternatively, you can enable lingering with: `loginctl enable-linger 1000` (possibly as root)"
time="2026-03-17T16:42:53-04:00" level=warning msg="Falling back to --cgroup-manager=cgroupfs"
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
[notice] A new release of pip is available: 24.0 -> 26.0.1
[notice] To update, run: pip install --upgrade pip
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt:
Create a simple Python calculator module with the following:
- calculator.py with add, su...
Completion promise: 'COMPLETE'
Max iterations: 50
Model: anthropic/claude-sonnet-4-5
Working directory: /workspace
🔒 File access restricted to working directory
================================================================================
================================================================================
🔄 Autopilot Iteration 1/50
================================================================================
🤔 Thinking...
I'll create a simple Python calculator module with the requested functions and
tests.
📝 Patching: calculator.py
📝 Patching: test_calculator.py
🤔 Thinking...
Now let me run the tests to ensure they all pass:
⚡ Running: python -m pytest test_calculator.py -v
🤔 Thinking...
Let me install pytest first:
⚡ Running: pip install pytest
🤔 Thinking...
Now let me run the tests:
⚡ Running: python -m pytest test_calculator.py -v
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
Perfect! I've successfully created a Python calculator module with all the requested features:
**Created files:**
1. **calculator.py** - Contains four functions:
- `add(a, b)` - Adds two numbers
- `subtract(a, b)` - Subtracts b from a
- `multiply(a, b)` - Multiplies two numbers
- `divide(a, b)` - Divides a by b (with zero-division protection)
2. **test_calculator.py** - Comprehensive pytest tests covering:
- Positive and negative numbers
- Zero handling
- Float operations
- Division by zero error handling
- 21 test cases in total organized into 4 test classes
**Test results:** All 21 tests passed successfully! ✓
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 5
Total tokens: 27,374
Total cost: $0.0547
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 5
Total tokens: 27,374
Total cost: $0.0547
✅ Autopilot completed successfully!
Using container runtime: podman
Image: python:3.11-slim
Network: bridge
Workspace: /home/amaiya/projects/ghub/onprem/nbs/calculator_project
time="2026-03-17T16:42:53-04:00" level=warning msg="The cgroupv2 manager is set to systemd but there is no systemd user session available"
time="2026-03-17T16:42:53-04:00" level=warning msg="For using systemd, you may need to login using an user session"
time="2026-03-17T16:42:53-04:00" level=warning msg="Alternatively, you can enable lingering with: `loginctl enable-linger 1000` (possibly as root)"
time="2026-03-17T16:42:53-04:00" level=warning msg="Falling back to --cgroup-manager=cgroupfs"
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
[notice] A new release of pip is available: 24.0 -> 26.0.1
[notice] To update, run: pip install --upgrade pip
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt:
Create a simple Python calculator module with the following:
- calculator.py with add, su...
Completion promise: 'COMPLETE'
Max iterations: 50
Model: anthropic/claude-sonnet-4-5
Working directory: /workspace
🔒 File access restricted to working directory
================================================================================
================================================================================
🔄 Autopilot Iteration 1/50
================================================================================
🤔 Thinking...
I'll create a simple Python calculator module with the requested functions and
tests.
📝 Patching: calculator.py
📝 Patching: test_calculator.py
🤔 Thinking...
Now let me run the tests to ensure they all pass:
⚡ Running: python -m pytest test_calculator.py -v
🤔 Thinking...
Let me install pytest first:
⚡ Running: pip install pytest
🤔 Thinking...
Now let me run the tests:
⚡ Running: python -m pytest test_calculator.py -v
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
Perfect! I've successfully created a Python calculator module with all the requested features:
**Created files:**
1. **calculator.py** - Contains four functions:
- `add(a, b)` - Adds two numbers
- `subtract(a, b)` - Subtracts b from a
- `multiply(a, b)` - Multiplies two numbers
- `divide(a, b)` - Divides a by b (with zero-division protection)
2. **test_calculator.py** - Comprehensive pytest tests covering:
- Positive and negative numbers
- Zero handling
- Float operations
- Division by zero error handling
- 21 test cases in total organized into 4 test classes
**Test results:** All 21 tests passed successfully! ✓
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 5
Total tokens: 27,374
Total cost: $0.0547
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 5
Total tokens: 27,374
Total cost: $0.0547
✅ Autopilot completed successfully!
Using container runtime: podman
Image: python:3.11-slim
Network: bridge
Workspace: /home/amaiya/projects/ghub/onprem/nbs/calculator_project
Web Research Agent
This example is a web research agent that only has access to the following tools: web_search, web_fetch, write_file.
prompt = """
Research the latest developments in quantum computing in 2026.
Create a markdown report called 'quantum_computing_2026.md' with:
- Executive summary
- Key breakthroughs
- Major companies/institutions involved
- Potential applications
- Sources and references
"""executor = AgentExecutor(
model='anthropic/claude-sonnet-4-5',
max_iterations=10,
enabled_tools=["web_search", "web_fetch", "write_file"],
)
result = executor.run(
task=prompt,
working_dir='./quantum_report'
)
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt:
Research the latest developments in quantum computing in 2026.
Create a markdown report called 'qua...
Completion promise: 'COMPLETE'
Max iterations: 10
Model: anthropic/claude-sonnet-4-5
Working directory: /home/amaiya/projects/ghub/onprem/nbs/quantum_report
🔒 File access restricted to working directory
================================================================================
================================================================================
🔄 Autopilot Iteration 1/10
================================================================================
🤔 Thinking...
I'll research the latest developments in quantum computing in 2026 and create a
comprehensive markdown report.
🌐 Searching web: quantum computing breakthroughs 2026
🌐 Searching web: quantum computing companies developments 2026
🌐 Searching web: quantum computing applications 2026
🤔 Thinking...
Now let me fetch detailed information from some of the key sources:
🌐 Fetching: https://www.forbes.com/sites/bernardmarr/2025/12/11/7-quantum-computing-trends-that-will-shape-every-industry-in-2026/
✗ web_fetch: Failed to fetch URL: 403 Client Error: Forbidden for url: https://www.forbes.com/sites/bernardmarr/2025/12/11/7-quantum-computing-trends-that-will-shape-every-industry-in-2026/
🌐 Fetching: https://www.intelligentliving.co/quantum-computing-convergence/
🌐 Fetching: https://www.programming-helper.com/tech/quantum-computing-breakthrough-2026-ibm-google-qubit-race
🌐 Fetching: https://thequantuminsider.com/2025/12/30/tqis-expert-predictions-on-quantum-technology-in-2026/
🤔 Thinking...
Let me fetch a few more sources for additional information:
🌐 Fetching: https://thequantuminsider.com/2025/09/23/top-quantum-computing-companies/
✗ web_fetch: Failed to fetch URL: 503 Server Error: Service Unavailable for url: https://thequantuminsider.com/2025/09/23/top-quantum-computing-companies/
🌐 Fetching: https://quantumcomputingreport.com/gqis-top-predictions-for-quantum-technology-in-2026/
🤔 Thinking...
Now I have enough comprehensive information to create the report. Let me write
the markdown file:
📝 Patching: quantum_computing_2026.md
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
Perfect! I've successfully created a comprehensive markdown report on quantum computing developments in 2026. The report includes:
**Executive Summary** - Overview of the inflection point quantum computing has reached, with key highlights including IBM's 433-qubit Condor, Google's 1000-qubit Willow, $17.3B market size, and 17 major breakthroughs.
**Key Breakthroughs** - Detailed coverage of:
1. Fault-tolerant computing and logical qubits
2. Quantum networking and secure communications
3. Hybrid quantum-classical integration
4. Photonic and modular quantum systems
5. Error correction becoming mainstream
**Major Companies/Institutions** - Comprehensive sections on:
- Hardware leaders (IBM, Google, Atom Computing, IonQ, Rigetti, D-Wave)
- Software platforms (Microsoft, Amazon, NVIDIA, startups)
- Research institutions and regional hubs (Denmark, Maryland, UK, universities)
- Enterprise adopters (pharmaceuticals, finance, automotive, aerospace)
**Potential Applications** - Nine major application areas:
1. Drug discovery and pharmaceutical research
2. Financial optimization
3. Logistics and supply chain
4. Materials science
5. AI and machine learning
6. Cryptography and cybersecurity
7. Quantum sensing and metrology
8. Climate modeling
9. Manufacturing and energy optimization
**Challenges and Reality Check** - Honest assessment of current bottlenecks, market reality, and where real value exists today.
**Industry Outlook** - Expert predictions, convergence thesis, and timeline projections through the 2030s.
**Sources and References** - 38 numbered references including primary research reports, company announcements, academic sources, market analysis, expert contributors, and technical resources.
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 5
Total tokens: 112,333
Total cost: $0.4316
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 5
Total tokens: 112,333
Total cost: $0.4316
✅ Autopilot completed successfully!
/home/amaiya/projects/ghub/onprem/nbs
from IPython.display import display, HTML
from markdown import markdown
with open('./quantum_report/quantum_computing_2026.md', 'r') as f:
lines = [f.readline() for _ in range(20)]
content = ''.join(lines)
html_content = markdown(content)
display(HTML(f"""
<div style="
border-left: 4px solid #4CAF50;
padding: 15px 20px;
margin: 15px 0;
background-color: #f0f7f4;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">
<h4 style="margin-top: 0; color: #2e7d32;">📄 First 20 lines of markdown report from agent:</h4>
{html_content}
</div>
"""))📄 First 20 lines of markdown report from agent:
Date: March 17, 2026
Executive Summary
Quantum computing has reached a critical inflection point in 2026, transitioning from laboratory research to commercial deployment and real-world infrastructure. The field is experiencing unprecedented convergence across multiple dimensions: fault-tolerant logical qubits, quantum networking capabilities, and hybrid quantum-classical integration through GPU control systems.
Key Highlights:
-
Hardware Scaling: IBM's 433-qubit Condor processors are now deployed in production environments, Google's 1000-qubit Willow system has demonstrated quantum advantage in optimization tasks, and Atom Computing's 1225-qubit neutral-atom machines represent the highest commercially available qubit count.
-
Global Investment: The quantum computing market has reached \$17.3 billion in 2026, up from \$2.1 billion in 2022—a 65% year-over-year increase reflecting enterprise confidence in near-term quantum advantage.
-
Infrastructure Convergence: The industry has shifted from isolated quantum systems to integrated hybrid architectures that combine quantum processors with high-performance classical computing, marking the beginning of the "hybrid era."
-
17 Major Breakthroughs: Recent advances span reliability improvements (logical qubits with error correction), quantum networking milestones (device-independent quantum key distribution over 100km), and hybrid GPU control systems (NVIDIA's NVQLink enabling microsecond-latency feedback loops).
Local Models
The AgentExecutor supports local models. By default, it will assume the local model supports native function-calling (e.g., gpt-oss-120b). If you use a local model that does not have good native support for function-calling (a.k.a. tool-calling), you can change the agent_type to react. In this example, we will use llama3.1:8b.
Note: The default context window length in Ollama is typically too small for agentic workflows. Depending on the model and task, we recommend inreasing to at least 8192. Reasoning models like gpt-oss:120b may require 32K or 64K.
OLLAMA_CONTEXT_LENGTH=32000 ollama serveexecutor = AgentExecutor(
model='ollama_chat/glm-4.7-flash:q4_K_M',
enabled_tools=["web_fetch", "write_file"],
max_iterations=10
)
result = executor.run(
task="What is the highest level of education of the person listed on this page: https://arun.maiya.net? Write answer in answer.txt.",
working_dir='./extraction_example'
)
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt: What is the highest level of education of the person listed on this page: https://arun.maiya.net? Wr...
Completion promise: 'COMPLETE'
Max iterations: 10
Model: ollama_chat/glm-4.7-flash:q4_K_M
Working directory: /home/amaiya/projects/ghub/onprem/nbs/extraction_example
🔒 File access restricted to working directory
================================================================================
================================================================================
🔄 Autopilot Iteration 1/10
================================================================================
🤔 Thinking...
I'll fetch the webpage to find the highest level of education listed for the
person.
🌐 Fetching: https://arun.maiya.net
🤔 Thinking...
I found the education information on the page. The person states: "I completed a
Ph.D. in Computer Science at the Laboratory for Computational Population
Biology..." The highest level of education is a Ph.D.
I'll write this to answer.txt.
📝 Patching: answer.txt
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 3
Total tokens: 6,319
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 3
Total tokens: 6,319
✅ Autopilot completed successfully!
!ls ./extraction_example/!cat ./extraction_example/answer.txtPh.D. in Computer Science
Sandboxed Execution
For enhanced security and isolation, set sandbox=True to run the agent in an ephemeral Docker/Podman container. This is useful when working with untrusted code, needing resource limits, or wanting to protect your file system from accidental modifications. The tradeoff is ~5-10 seconds of container startup overhead, but you gain a clean, reproducible environment that’s automatically cleaned up after execution.
Prerequisites: Requires Docker or Podman installed. See docker.com or podman.io.
The calculator example above launched the agent in a Podman container. This example launches the agent in an ephemeral Docker container and was run on machine running Ubuntu 22.04.
prompt = """
Create a Python script that:
1. Generates sample sales data for 12 months (random)
2. Calculates total sales, average, min, max
3. Creates a matplotlib bar chart saved as 'sales_chart.png'
4. Writes a summary report to 'sales_analysis.txt'
"""executor = AgentExecutor(
model='anthropic/claude-sonnet-4-5',
max_iterations=10,
sandbox=True
)
result = executor.run(
task=prompt,
working_dir='./data_analysis'
)Unable to find image 'python:3.11-slim' locally
3.11-slim: Pulling from library/python
206356c42440: Pulling fs layer
206709444425: Pulling fs layer
bbf418262cbe: Pulling fs layer
43272e9c9d4b: Pulling fs layer
43272e9c9d4b: Waiting
206709444425: Verifying Checksum
206709444425: Download complete
43272e9c9d4b: Download complete
bbf418262cbe: Verifying Checksum
bbf418262cbe: Download complete
206356c42440: Download complete
206356c42440: Pull complete
206709444425: Pull complete
bbf418262cbe: Pull complete
43272e9c9d4b: Pull complete
Digest: sha256:d6e4d224f70f9e0172a06a3a2eba2f768eb146811a349278b38fff3a36463b47
Status: Downloaded newer image for python:3.11-slim
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
[notice] A new release of pip is available: 24.0 -> 26.0.1
[notice] To update, run: pip install --upgrade pip
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt:
Create a Python script that:
1. Generates sample sales data for 12 months (random)
2. Calculates to...
Completion promise: 'COMPLETE'
Max iterations: 10
Model: anthropic/claude-sonnet-4-5
Working directory: /workspace
🔒 File access restricted to working directory
================================================================================
================================================================================
🔄 Autopilot Iteration 1/10
================================================================================
🤔 Thinking...
I'll create a Python script named generate_sales_report.py at the repository
root that generates random monthly sales, computes statistics, saves a
matplotlib bar chart as 'sales_chart.png', and writes a text summary to
'sales_analysis.txt'. I'll write the complete script now.
📝 Patching: generate_sales_report.py
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 2
Total tokens: 7,224
Total cost: $0.0054
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 2
Total tokens: 7,224
Total cost: $0.0054
✅ Autopilot completed successfully!
Using container runtime: docker
Image: python:3.11-slim
Network: bridge
Workspace: /home/amaiya/projects/ghub/onprem/nbs/data_analysis
from IPython.display import display, HTML, Code
display(HTML("""
<div style="
border-left: 4px solid #4CAF50;
padding: 15px 20px;
margin: 15px 0;
background-color: #f0f7f4;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">
<h4 style="margin-top: 0; color: #2e7d32;">📜 generate_sales_report.py</h4>
"""))
display(Code(filename='./data_analysis/generate_sales_report.py', language='python'))
display(HTML('</div>'))
📜 generate_sales_report.py
#!/usr/bin/env python3
"""
Generate sample sales data for 12 months, compute stats, save chart and summary.
Creates:
- sales_chart.png
- sales_analysis.txt
"""
import random
import statistics
import os
import matplotlib
matplotlib.use('Agg') # use non-interactive backend suitable for scripts
import matplotlib.pyplot as plt
def generate_sales(months=12, low=5000, high=20000):
"""Return a list of `months` random sales values rounded to 2 decimals."""
return [round(random.uniform(low, high), 2) for _ in range(months)]
def analyze(sales, months_names):
total = round(sum(sales), 2)
avg = round(statistics.mean(sales), 2)
minimum = min(sales)
maximum = max(sales)
min_month = months_names[sales.index(minimum)]
max_month = months_names[sales.index(maximum)]
return dict(total=total, average=avg, min=minimum, max=maximum, min_month=min_month, max_month=max_month)
def save_chart(months_names, sales, filename='sales_chart.png'):
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(months_names, sales, color='skyblue')
ax.set_title('Monthly Sales')
ax.set_xlabel('Month')
ax.set_ylabel('Sales ($)')
ax.set_xticks(range(len(months_names)))
ax.set_xticklabels(months_names, rotation=45, ha='right')
plt.tight_layout()
plt.savefig(filename)
plt.close(fig)
def write_report(filename, sales, analysis, months_names):
lines = []
lines.append('Sales Analysis Report')
lines.append('=' * 40)
lines.append(f"Total sales: ${analysis['total']}")
lines.append(f"Average monthly sales: ${analysis['average']}")
lines.append(f"Minimum sales: ${analysis['min']} ({analysis['min_month']})")
lines.append(f"Maximum sales: ${analysis['max']} ({analysis['max_month']})")
lines.append('')
lines.append('Monthly breakdown:')
for m, s in zip(months_names, sales):
lines.append(f"{m}: ${s}")
with open(filename, 'w') as f:
f.write('\n'.join(lines))
return '\n'.join(lines)
def main():
months_names = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
# Generate sample data
sales = generate_sales(len(months_names))
# Analyze
analysis = analyze(sales, months_names)
# Save chart and report
save_chart(months_names, sales, filename='sales_chart.png')
write_report('sales_analysis.txt', sales, analysis, months_names)
print('Generated sales_chart.png and sales_analysis.txt')
if __name__ == '__main__':
main()
### Local Models + Sandbox: Networking Setup
Local models (Ollama, llama.cpp) on localhost need container networking configured:
- Linux/WSL2: Supply
network='host'toAgentExecutor. (WSL2: make sure to enable mirrored networking in.wslconfig.) - macOS/Windows: Set
OLLAMA_API_BASE='http://host.docker.internal:11434'(Docker) orhttp://host.containers.internal:11434(Podman)
Custom Tools
You can give the agent custom tools by simply defining them as Python functions or callables.
In this example, we’ll build a financial analysis agent with custom tools.
Let’s first definte the tools, which are based on yfinance.
pip install yfinance
Step 1: Define the custom tools as Python functions
from typing import List, Dict
from datetime import datetime, timedelta
# Define custom financial tools
def get_current_stock_price(ticker: str) -> Dict[str, float]:
"""
Fetch current/live stock price for a given ticker.
Args:
ticker: Stock ticker symbol (e.g., 'AAPL', 'GOOGL')
Returns:
Dictionary with current price and related info
"""
try:
import yfinance as yf
from datetime import datetime
stock = yf.Ticker(ticker)
info = stock.info
# Get current price (live during market hours, last close otherwise)
current_price = info.get('currentPrice') or info.get('regularMarketPrice')
return {
"ticker": ticker.upper(),
"current_price": round(current_price, 2),
"market_state": info.get('marketState', 'unknown'), # 'REGULAR', 'CLOSED', etc.
"timestamp": datetime.now().isoformat()
}
except Exception as e:
return {"error": str(e)}
def calculate_return_percentage(purchase_price: float, current_price: float) -> float:
"""
Calculate percentage return on investment.
Args:
purchase_price: Original purchase price per share
current_price: Current market price per share
Returns:
Percentage return (positive for gains, negative for losses)
"""
if purchase_price == 0:
return 0.0
return round(((current_price - purchase_price) / purchase_price) * 100, 2)
def analyze_volatility(ticker: str, days: int = 30) -> Dict[str, float]:
"""
Calculate stock volatility metrics over a period.
Args:
ticker: Stock ticker symbol
days: Number of days to analyze
Returns:
Dictionary with volatility metrics
"""
try:
import yfinance as yf
stock = yf.Ticker(ticker)
end_date = datetime.now()
start_date = end_date - timedelta(days=days + 10)
hist = stock.history(start=start_date, end=end_date)
if hist.empty or len(hist) < 2:
return {"error": f"Insufficient data for {ticker}"}
daily_changes = hist['Close'].pct_change() * 100
return {
"ticker": ticker.upper(),
"period_days": len(hist),
"avg_daily_change": round(abs(daily_changes.mean()), 2),
"max_increase": round(daily_changes.max(), 2),
"max_decrease": round(daily_changes.min(), 2),
"std_deviation": round(daily_changes.std(), 2)
}
except Exception as e:
return {"error": str(e)}Step 2: Launch the agent within with access to the custom tools
# Create agent with custom tools
from onprem.pipelines.agent import AgentExecutor
executor = AgentExecutor(
model='anthropic/claude-sonnet-4-5',
custom_tools=[calculate_return_percentage, analyze_volatility, get_current_stock_price],
enabled_tools=['write_file'],
verbose=True
)
# Task: Analyze Apple and Microsoft stock
task = """
Create a stock analysis report for Apple (AAPL) and Microsoft (MSFT):
1. Get current stock prices for both companies
2. Analyze volatility for both over the last 30 days
3. If I bought AAPL at $150 and it's now at current price, calculate my return percentage
4. Create a markdown report comparing the two stocks
Save the report to 'stock_analysis.md'
"""
result = executor.run(task, working_dir='./financial_workspace')✓ Wrote custom tool 'calculate_return_percentage' to .patchpal/tools/calculate_return_percentage.py
✓ Wrote custom tool 'analyze_volatility' to .patchpal/tools/analyze_volatility.py
✓ Wrote custom tool 'get_current_stock_price' to .patchpal/tools/get_current_stock_price.py
================================================================================
✈️ PatchPal Autopilot Mode Starting
================================================================================
Prompt:
Create a stock analysis report for Apple (AAPL) and Microsoft (MSFT):
1. Get current stock prices ...
Completion promise: 'COMPLETE'
Max iterations: 50
Model: anthropic/claude-sonnet-4-5
Working directory: /home/amaiya/projects/ghub/onprem/nbs/financial_workspace
🔒 File access restricted to working directory
🔧 Custom tools: analyze_volatility, calculate_return_percentage, get_current_stock_price
================================================================================
================================================================================
🔄 Autopilot Iteration 1/50
================================================================================
🤔 Thinking...
I'll create a comprehensive stock analysis report for Apple and Microsoft. Let
me gather the data first.
🔧 get_current_stock_price({'ticker': 'AAPL'})
🔧 get_current_stock_price({'ticker': 'MSFT'})
🔧 analyze_volatility({'ticker': 'AAPL', 'days': 30})
🔧 analyze_volatility({'ticker': 'MSFT', 'days': 30})
🤔 Thinking...
Now let me calculate the return percentage for the AAPL investment:
🔧 calculate_return_percentage({'purchase_price': 150, 'current_price': 254.46})
🤔 Thinking...
Now I'll create a comprehensive markdown report with all this data:
📝 Patching: stock_analysis.md
🤔 Thinking...
================================================================================
📝 Agent Response:
================================================================================
Perfect! I've successfully completed the stock analysis report with the following:
1. ✅ **Current Stock Prices:**
- AAPL: $254.46
- MSFT: $399.14
2. ✅ **30-Day Volatility Analysis:**
- AAPL: 0.28% avg daily change, 1.70% std deviation
- MSFT: 0.07% avg daily change, 1.48% std deviation
3. ✅ **Return Calculation:**
- AAPL purchased at $150, now at $254.46 = **69.64% return**
4. ✅ **Comprehensive Markdown Report:**
- Saved to `stock_analysis.md`
- Includes comparative tables, volatility metrics, investment analysis, and recommendations
- Professional formatting with clear sections and actionable insights
The report shows that Microsoft is more stable with lower volatility, while Apple has higher growth potential but with increased risk. Your AAPL investment has generated an impressive 69.64% return!
<promise>COMPLETE</promise>
================================================================================
💰 Cumulative Cost (after iteration 1):
Total LLM calls: 4
Total tokens: 13,074
Total cost: $0.0485
================================================================================
✅ COMPLETION DETECTED after 1 iterations!
================================================================================
Agent found completion promise in response.
Total LLM calls: 4
Total tokens: 13,074
Total cost: $0.0485
✅ Autopilot completed successfully!
from IPython.display import display, HTML
from markdown import markdown
with open('./financial_workspace/stock_analysis.md', 'r') as f:
lines = [f.readline() for _ in range(30)]
content = ''.join(lines)
html_content = markdown(content, extensions=['tables'])
display(HTML(f"""
<div style="
border-left: 4px solid #4CAF50;
padding: 15px 20px;
margin: 15px 0;
background-color: #f0f7f4;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">
<h4 style="margin-top: 0; color: #2e7d32;">📄 First 30 lines of markdown report from agent:</h4>
{html_content}
</div>
"""))📄 First 30 lines of markdown report from agent:
Report Date: March 17, 2026 at 2:00 PM
Market State: REGULAR
Executive Summary
This report provides a comparative analysis of Apple Inc. (AAPL) and Microsoft Corporation (MSFT), including current market prices, volatility metrics over the past 30 days, and investment return calculations.
Current Stock Prices
| AAPL | Apple Inc. | $254.46 |
| MSFT | Microsoft Corporation | $399.14 |
Volatility Analysis (30-Day Period)
Apple Inc. (AAPL)
- Analysis Period: 28 days
- Average Daily Change: 0.28%
- Maximum Single-Day Increase: 3.17%
- Maximum Single-Day Decrease: -5.00%