| name | programmatic-tool-calling |
| description | Multi-step tool workflows via code orchestration to reduce latency, context pollution, and token overhead. |
Programmatic Tool Calling Skill (Model-Agnostic)
Purpose
Execute multi-step tool workflows via code orchestration to reduce latency, context pollution, and token overhead.
Use when
- 3+ dependent tool calls
- Large intermediate outputs (logs, tables, files)
- Branching logic, retries, or fan-out/fan-in workflows
Core Idea
Treat tools as callable functions inside an orchestration runtime (script/runner), not as one-turn-at-a-time chat actions.
Procedure
- Generate/execute orchestration code for loops, conditionals, parallel calls, retries, and early termination.
- Process intermediate data in runtime (filter/aggregate/transform) instead of returning raw data to model context.
- Return only high-signal outputs to the model (summary, decision, artifact references).
Example — Multi-file lint check with summary
async function lintAllFiles(files) {
const results = [];
const promises = files.map(file =>
runTool("run_command", { cmd: `eslint ${file} --format json` })
);
const outputs = await Promise.allSettled(promises);
for (const [i, output] of outputs.entries()) {
if (output.status === "rejected" || output.value.exitCode !== 0) {
const parsed = JSON.parse(output.value?.stdout || "[]");
const errors = parsed.filter(r => r.errorCount > 0);
if (errors.length) {
results.push({
file: files[i],
errorCount: errors[0].errorCount,
topError: errors[0].messages[0]?.message
});
}
}
}
return {
totalFiles: files.length,
failedFiles: results.length,
failures: results
};
}
Key: the raw lint JSON never enters the model context — only the filtered summary does.
Example — HarnessOS lifecycle orchestration
Use code orchestration when the workflow is “discover -> claim -> checkpoint -> close” and intermediate payloads are large:
async function executeReadyIssue(projectName) {
const capabilities = await runTool("harness_inspector", { action: "capabilities" });
validateCapabilities(capabilities);
const begin = await runTool("harness_session", {
action: "begin",
projectName,
});
if (begin.status !== "ok" || !begin.sessionToken) {
return { claimed: false, reason: "No ready issue" };
}
const summary = await performWorkOutsideModelContext(begin.issueId);
await runTool("harness_session", {
action: "checkpoint",
sessionToken: begin.sessionToken,
input: {
title: "Implementation complete",
summary,
taskStatus: "in_progress",
nextStep: "Run final validation",
},
});
return runTool("harness_session", {
action: "close",
sessionToken: begin.sessionToken,
closeInput: {
title: "Task complete",
summary,
taskStatus: "done",
nextStep: "Wait for feedback",
},
});
}
The important part is not the exact code — it is that the heavy work stays in the orchestration runtime and only compact lifecycle summaries come back to the model.
Why It Works (provider/model independent)
- Fewer model round-trips for multi-call workflows.
- Intermediate data stays out of context unless needed.
- Explicit code control flow is easier to test, monitor, and debug.
Guardrails
- Strict input/output schemas.
- Validate tool results before use.
- Idempotent/retry-safe tool design when possible.
- Timeout/cancellation/expiry handling.
- Sandbox execution for untrusted code; never blindly execute external payloads.
- Do not mutate canonical state outside the official HarnessOS tool surface just because orchestration code makes it easy.
Done Criteria
- Workflow completes with reduced context load and deterministic control flow.
Anti-patterns
- Returning raw intermediate payloads to the model by default
- Unbounded loops without stop conditions
- Executing unvalidated tool output