Programatic Tool Calling (PTC) with the Haijun API
Programmatic Tool Calling (PTC) allows Haijun to write code that calls tools programmatically within the Code Execution environment, rather than requiring round-trips through the model for each tool invocation. This substantially reduces end-to-end latency for multiple tool calls, and can dramatically reduce token consumption by allowing the model to write code that removes irrelevant context before it hits the model’s context window (for example, by grepping for key information within large and noisy files).
When faced with third-party APIs and tools that you may not be able to modify directly, PTC can help reduce usage of context by allowing Haijun to write code that can be invoked in the Code Execution environment.
regular tool calling and programatic tool calling (PTC)
Write agents that leverage PTC
Prerequisites
%pip install -r requirements.txt
Note: Ensure your .env file contains:
ll-region max-h-[inherit] min-h-0 flex-1 overflow-auto scroll-fade-y scroll-fade-size-6 focus-visible:outline-none">
import json
import juglow
from utils.team_expense_api import get_custom_budget, get_expenses, get_team_members
client = juglow.Juglow()
Tool definitions for the team expense API
tools = [
{
"name": "get_team_members",
"description": 'Returns a list of team members for a given department. Each team member includes their ID, name, role, level (junior, mid, senior, staff, principal), and contact information. Use this to get a list of people whose expenses you want to analyze. Available departments are: engineering, sales, and marketing.\n\nRETURN FORMAT: Returns a JSON string containing an ARRAY of team member objects (not wrapped in an outer object). Parse with json.loads() to get a list. Example: [{"id": "ENG001", "name": "Alice", ...}, {"id": "ENG002", ...}]',
"input_schema": {
"type": "object",
"properties": {
"department": {
"type": "string",
"description": "The department name. Case-insensitive.",
}
},
"required": ["department"],
},
"input_examples": [
{"department": "engineering"},
{"department": "sales"},
{"department": "marketing"},
],
},
{
"name": "get_expenses",
"description": "Returns all expense line items for a given employee in a specific quarter. Each expense includes extensive metadata: date, category, description, amount (in USD), currency, status (approved, pending, rejected), receipt URL, approval chain, merchant name and location, payment method, and project codes. An employee may have 20-50+ expense line items per quarter, and each line item contains substantial metadata for audit and compliance purposes. Categories include: 'travel' (flights, trains, rental cars, taxis, parking), 'lodging' (hotels, airbnb), 'meals', 'software', 'equipment', 'conference', 'office', and 'internet'. IMPORTANT: Only expenses with status='approved' should be counted toward budget limits.\n\nRETURN FORMAT: Returns a JSON string containing an ARRAY of expense objects (not wrapped in an outer object with an 'expenses' key). Parse with json.loads() to get a list directly. Example: [{\"expense_id\": \"ENG001_Q3_001\", \"amount\": 1250.50, \"category\": \"travel\", ...}, {...}]",
"input_schema": {
"type": "object",
"properties": {
"employee_id": {
"type": "string",
"description": "The unique employee identifier",
},
"quarter": {
"type": "string",
"description": "Quarter identifier: 'Q1', 'Q2', 'Q3', or 'Q4'",
},
},
"required": ["employee_id", "quarter"],
},
"input_examples": [
{"employee_id": "ENG001", "quarter": "Q3"},
{"employee_id": "SAL002", "quarter": "Q1"},
{"employee_id": "MKT001", "quarter": "Q4"},
],
},
{
"name": "get_custom_budget",
"description": 'Get the custom quarterly travel budget for a specific employee. Most employees have a standard $5,000 quarterly travel budget. However, some employees have custom budget exceptions based on their role requirements. This function checks if a specific employee has a custom budget assigned.\n\nRETURN FORMAT: Returns a JSON string containing a SINGLE OBJECT (not an array). Parse with json.loads() to get a dict. Example: {"user_id": "ENG001", "has_custom_budget": false, "travel_budget": 5000, "reason": "Standard", "currency": "USD"}',
"input_schema": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"description": "The unique employee identifier",
}
},
"required": ["user_id"],
},
"input_examples": [
{"user_id": "ENG001"},
{"user_id": "SAL002"},
{"user_id": "MKT001"},
],
},
]
tool_functions = {
"get_team_members": get_team_members,
"get_expenses": get_expenses,
"get_custom_budget": get_custom_budget,
}
Traditional Tool Calling (Baseline)
t;employee_id": "ENG002",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
├──
Block 4
│
│
│ └──
Tool Use:
get_expenses
│
│
│ ├──
ID:
toolu_01RjjhZTg9JsKXE5E9S6Foho
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "employee_id": "ENG003",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
├──
Block 5
│
│
│ └──
Tool Use:
get_expenses
│
│
│ ├──
ID:
toolu_013xqpxpfc2N9rP5W5uMLAo9
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "employee_id": "ENG004",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
├──
Block 6
│
│
│ └──
Tool Use:
get_expenses
│
│
│ ├──
ID:
toolu_019zfzG6Wox8iDqy1dUXiH3t
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "employee_id": "ENG005",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
├──
Block 7
│
│
│ └──
Tool Use:
get_expenses
│
│
│ ├──
ID:
toolu_01RxfTz11tzvbVE7oEtqHaVB
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "employee_id": "ENG006",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
├──
Block 8
│
│
│ └──
Tool Use:
get_expenses
│
│
│ ├──
ID:
toolu_01FsFEtK1gTEPxg56eVrhhf6
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "employee_id": "ENG007",
│
│
│ "quarter": "Q3"
│
│
│ }
│
│
└──
Block 9
│
│
└──
Tool Use:
get_expenses
│
│
├──
ID:
toolu_01Ctq9dZbvzaVSLSZe86MTzb
│
│
├──
Caller:
model (direct)
│
│
└──
Input:
│
│
└── {
│
│
"employee_id": "ENG008",
│
│
"quarter": "Q3"
│
│
}
│
╰──────────────────────────────────────────────────────────────────────────────────╯
╭─
─────────────────────────────────────────────
Haijun API Response
─────────────────────────────────────────────
─╮
│
Haijun Message
(
assistant
)
│
tokens:
51,744
in •
290
out •
52,034
total
│
│
├──
Model:
haijun-sonnet-4-6
│
│
├──
Stop Reason:
tool_use
│
│
└──
Content
(7 blocks)
│
│
├──
Block 1
│
│
│ └──
Text
│
│
│ └──
Now let me calculate the approved travel expenses for each engineer and identify who exceeded
│
│
│
$5,000:
│
│
├──
Block 2
│
│
│ └──
Tool Use:
get_custom_budget
│
│
│ ├──
ID:
toolu_013oegKwjvToLwEW1daDD8av
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "user_id": "ENG001"
│
│
│ }
│
│
├──
Block 3
│
│
│ └──
Tool Use:
get_custom_budget
│
│
│ ├──
ID:
toolu_0162W4Ycr9FcVVED65exjAj4
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "user_id": "ENG003"
│
│
│ }
│
│
├──
Block 4
│
│
│ └──
Tool Use:
get_custom_budget
│
│
│ ├──
ID:
toolu_01JcTX5rnwFxA99Am33gXmh6
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "user_id": "ENG005"
│
│
│ }
│
│
├──
Block 5
│
│
│ └──
Tool Use:
get_custom_budget
│
│
│ ├──
ID:
toolu_01QwNJz1wGeV5VeZoCd4ByER
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "user_id": "ENG006"
│
│
│ }
│
│
├──
Block 6
│
│
│ └──
Tool Use:
get_custom_budget
│
│
│ ├──
ID:
toolu_01KoJ4gzfiu1TPccLJB86Wiq
│
│
│ ├──
Caller:
model (direct)
│
│
│ └──
Input:
│
│
│ └── {
│
│
│ "user_id": "ENG007"
│
│
│ }
│
│
└──
Block 7
│
│
└──
Tool Use:
get_custom_budget
│
│
├──
ID:
toolu_01MxeFPzHot9aE5fPuniFkui
│
│
├──
Caller:
model (direct)
│
│
└──
Input:
│
│
└── {
│
│
"user_id": "ENG008"
│
│
}
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─
─────────────────────────────────────────────
Haijun API Response
─────────────────────────────────────────────
─╮
│
Haijun Message
(
assistant
)
│
tokens:
52,533
in •
992
out •
53,525
total
│
│
├──
Model:
haijun-sonnet-4-6
│
│
├──
Stop Reason:
end_turn
│
│
└──
Content
(1 blocks)
│
│
└──
Block 1
│
│
└──
Text
│
│
└──
Now let me analyze the data. I'll calculate the approved travel expenses for each engineer:
│
│
│
│
Analysis of Q3 Travel Expenses:
│
│
│
│
ENG001 - Alice Chen (Senior Software Engineer)
│
│
- Approved travel expenses: $1,161.04 + $18.63 + $13.21 + $36.55 + $1,440.42 + $166.46 + $48.43
│
│
+ $1,124.56 + $1,245.90 + $1,498.42 = $6,753.62
│
│
- Budget: $5,000 (Standard)
│
│
- EXCEEDED by $1,753.62 ❌
│
│
│
│
ENG002 - Bob Martinez (Staff Engineer)
│
│
- Approved travel expenses: $180.16 + $10.07 + $20.76 = $210.99
│
│
- Budget: $5,000 (Standard)
│
│
- Under budget ✓
│
│
│
│
ENG003 - Carol White (Software Engineer)
│
│
- Approved travel expenses: $24.75 + $424.74 + $1,397.17 + $1,026.12 + $1,288.36 + $1,128.90 +
│
│
$1,148.42 + $45.03 = $6,483.49
│
│
- Budget: $5,000 (Standard)
│
│
- EXCEEDED by $1,483.49 ❌
│
│
│
│
ENG004 - David Kim (Principal Engineer)
│
│
- Approved travel expenses: $21.68 + $46.12 + $1,008.68 + $46.43 = $1,122.91
│
│
- Budget: $5,000 (Standard)
│
│
- Under budget ✓
│
│
│
│
**ENG005 - Emma Johnson (Junior Software Engineer)
│
│
... (truncated)
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Result: Now let me analyze the data. I'll calculate the approved travel expenses for each engineer: Analysis of Q3 Travel Expenses: ENG001 - Alice Chen (Senior Software Engineer) - Approved travel expenses: $1,161.04 + $18.63 + $13.21 + $36.55 + $1,440.42 + $166.46 + $48.43 + $1,124.56 + $1,245.90 + $1,498.42 = $6,753.62 - Budget: $5,000 (Standard) - EXCEEDED by $1,753.62 ❌ ENG002 - Bob Martinez (Staff Engineer) - Approved travel expenses: $180.16 + $10.07 + $20.76 = $210.99 - Budget: $5,000 (Standard) - Under budget ✓ ENG003 - Carol White (Software Engineer) - Approved travel expenses: $24.75 + $424.74 + $1,397.17 + $1,026.12 + $1,288.36 + $1,128.90 + $1,148.42 + $45.03 = $6,483.49 - Budget: $5,000 (Standard) - EXCEEDED by $1,483.49 ❌ ENG004 - David Kim (Principal Engineer) - Approved travel expenses: $21.68 + $46.12 + $1,008.68 + $46.43 = $1,122.91 - Budget: $5,000 (Standard) - Under budget ✓ ENG005 - Emma Johnson (Junior Software Engineer) - Approved travel expenses: $450.00 + $1,376.36 + $1,164.49 + $151.55 + $1,253.88 = $4,396.28 - Budget: $5,000 (Standard) - Under budget ✓ ENG006 - Frank Liu (Senior Software Engineer) - Approved travel expenses: $596.48 + $1,018.71 + $1,193.82 + $159.08 + $1,112.11 + $24.97 = $4,105.17 - Budget: $5,000 (Standard) - Under budget ✓ ENG007 - Grace Taylor (Software Engineer) - Approved travel expenses: $1,476.63 + $39.85 + $1,220.19 + $189.16 + $1,032.52 + $1,331.00 = $5,289.35 - Budget: $5,000 (Standard) - EXCEEDED by $289.35 ❌ ENG008 - Henry Park (Staff Engineer) - Approved travel expenses: $15.63 + $166.05 + $1,018.94 + $1,224.34 + $1,120.32 + $1,345.90 = $4,891.18 - Budget: $5,000 (Standard) - Under budget ✓ --- ## Summary: Engineering Team Members Who Exceeded Their Q3 Travel Budget 3 team members exceeded their quarterly travel budget: 1. Alice Chen (ENG001) - Senior Software Engineer - Travel expenses: $6,753.62 - Budget: $5,000 - Over budget by $1,753.62 (35% over) 2. Carol White (ENG003) - Software Engineer - Travel expenses: $6,483.49 - Budget: $5,000 - Over budget by $1,483.49 (30% over) 3. Grace Taylor (ENG007) - Software Engineer - Travel expenses: $5,289.35 - Budget: $5,000 - Over budget by $289.35 (6% over) All three employees have the standard $5,000 quarterly travel budget with no custom exceptions. API calls made: 4 Total tokens used: 110,473 Total time taken: 35.38s
Great! We can see that Haijun was able to use the available tools successfully to identify which team members exceeded their travel budgets. However, we can also see that we used a lot of tokens to accomplish this task. Haijun had to ingest all the expense line items through its context window—potentially 100+ records per employee, each with extensive metadata including receipt URLs, approval chains, merchant information, and more—in order to parse them, sum up the totals by category, and compare against budget limits.
f"{((elapsed_time - elapsed_time_ptc) / elapsed_time * 100):.1f}%",
],
}
df = pd.DataFrame(comparison_data)
print(df.to_string(index=False))
Metric Traditional PTC API Calls 4 4 Total Tokens 110,473 15,919 Elapsed Time (s) 35.38 34.88 Token Reduction - 85.6% Time Reduction - 1.4% Key Takeaways In this example, PTC demonstrated significant performance improvements through three core capabilities: