|
| 1 | +# Tools in the Agent primitive + PTRR |
| 2 | + |
| 3 | +How tools are **documented**, **selected**, **parameterized**, **executed**, and |
| 4 | +**result-interpolated** for Bitcode agents. |
| 5 | + |
| 6 | +Related packages: |
| 7 | + |
| 8 | +| Package | Role | |
| 9 | +| --- | --- | |
| 10 | +| `@bitcode/tools-generics` | `Tool`, DocCodeToolPrompt, `formatUsableTools` | |
| 11 | +| `@bitcode/agent-generics` | AgentExecution tools registry, PTRR step postprocess, interpolations | |
| 12 | +| `@bitcode/generic-agents-ptrr` | PTRRAgent base (Plan→Try→Refine→Retry) | |
| 13 | +| `@bitcode/generic-doc-comments-doc-code` | Build-time `@doc-code-tool` → prompt attachment | |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## 1. End-to-end lifecycle |
| 18 | + |
| 19 | +``` |
| 20 | +Register tools on AgentExecution.tools (or parent pipeline registry) |
| 21 | + ↓ |
| 22 | +PTRR step starts → store tools.usable = Object.keys(getUsableTools()) |
| 23 | + ↓ |
| 24 | +FailsafeGeneration ×3 (PCC → ChunkThenSum → Stitch) |
| 25 | + each runs ThinkingsGeneration (Reason → Judge → StructuredOutput) |
| 26 | + ↓ [before each Thinkings LLM call] |
| 27 | + Doc interpolation: auto:tools_doc_code_tools ← formatUsableTools(usable) |
| 28 | + Results interpolation: auto:tools_results ← prior usedTools (if any) |
| 29 | + ↓ |
| 30 | +StructuredOutput may include: |
| 31 | + useTools: [{ name, input, reason }, ...] |
| 32 | + ↓ |
| 33 | +Step postprocess (conditional): |
| 34 | + if useTools?.length → factoryToolsExecution() |
| 35 | + ↓ |
| 36 | +For each selection: |
| 37 | + tool = execution.tools.getTool(name) |
| 38 | + output = tool.execute(input) |
| 39 | + usedTools.push({ tool: name, input, output } | { tool, error }) |
| 40 | + ↓ |
| 41 | +Store tools.use / tools.used; publish agent-step work update |
| 42 | + ↓ |
| 43 | +Next PTRR step (Refine/Retry) sees usedTools via results interpolation |
| 44 | +``` |
| 45 | + |
| 46 | +Tools run **once per step**, **after** failsafes — never inside Reason/Judge as |
| 47 | +side effects. Selection is declarative JSON; execution is deterministic registry lookup. |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +## 2. Doc-code → usable tool documentation (doc interpolation) |
| 52 | + |
| 53 | +### Authoring a tool |
| 54 | + |
| 55 | +```ts |
| 56 | +/** |
| 57 | + * @doc-code-tool |
| 58 | + * @purpose Search Depository for Need-fitting AssetPack evidence |
| 59 | + * @capabilities lexical search, source-safe snippets, ranked candidates |
| 60 | + * @parameters query: string; limit?: number |
| 61 | + * @output { candidates: Array<{ id, score, summary }> } |
| 62 | + */ |
| 63 | +class AssetPackLexicalDepositorySearchTool extends ExecutionTool<typeof searchFn> { |
| 64 | + use = searchFn; |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +Build-time **doc-code** (`@bitcode/generic-doc-comments-doc-code`) attaches a |
| 69 | +`DocCodeToolPrompt` instance to `tool.__docCodePrompt` (and `__promptParts`). |
| 70 | +Runtime fallback: `attachDocCodeToolPrompt(tool, prompt)` / `factoryTool({ prompt })`. |
| 71 | + |
| 72 | +### Formatting for the LLM |
| 73 | + |
| 74 | +```ts |
| 75 | +import { formatUsableTools } from '@bitcode/tools-generics'; |
| 76 | +// alias of formatToolsWithDocCodeToolsIntoUsableTools |
| 77 | + |
| 78 | +const docs = formatUsableTools(Object.values(execution.tools.getUsableTools())); |
| 79 | +// Sections: metadata, purpose, capabilities, parameters, output |
| 80 | +``` |
| 81 | + |
| 82 | +### Injection path (automatic) |
| 83 | + |
| 84 | +`factoryLLMSubStep` (Thinkings generations) calls |
| 85 | +`injectToolInterpolationsForGeneration` → |
| 86 | +`injectUsableToolDocsIntoPrompt`: |
| 87 | + |
| 88 | +| Prompt path | Content | |
| 89 | +| --- | --- | |
| 90 | +| `auto:tools_doc_code_tools` | Concatenated DocCodeToolPrompt `.format()` for every usable tool | |
| 91 | + |
| 92 | +`buildHierarchicalPrompt` then includes those parts in the system prompt. |
| 93 | +`ThinkingsGenerationPrompt.injectToolDocs` is the same semantic slot for |
| 94 | +declarative prompt carriers. |
| 95 | + |
| 96 | +**Without docs:** tools still execute if selected by name, but the model has no |
| 97 | +parameter schema — always attach DocCodeToolPrompt for production tools. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## 3. Parameters (how the model fills `input`) |
| 102 | + |
| 103 | +| Layer | Contract | |
| 104 | +| --- | --- | |
| 105 | +| Doc-code `@parameters` | Human/LLM-readable parameter description in usable tools block | |
| 106 | +| Structured schema | Agent/step Zod schema may declare `useTools: z.array(z.object({ name, input, reason }))` | |
| 107 | +| Reason shape | Default ReasoningSchema allows optional `useTools` | |
| 108 | +| Runtime selection | `output.useTools[].name` + `output.useTools[].input` | |
| 109 | + |
| 110 | +Canonical selection object: |
| 111 | + |
| 112 | +```json |
| 113 | +{ |
| 114 | + "name": "bitcode.asset-pack.verification", |
| 115 | + "input": { "repositoryFullName": "org/repo" }, |
| 116 | + "reason": "verify source-bound candidate evidence" |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +`factoryToolsExecution` also accepts: |
| 121 | + |
| 122 | +- `parameters` as synonym for `input` |
| 123 | +- `tool` as string name (legacy) when `name` omitted |
| 124 | + |
| 125 | +Lookup: **`AgentToolsRegistry.getTool(name)`** — current level, then parent |
| 126 | +pipeline/agent registries. `restrictTo(keys)` can deny non-allowed names. |
| 127 | + |
| 128 | +`ExecutionTool.execute` stores under a child execution: |
| 129 | + |
| 130 | +- `tool.name`, `tool.input` (args), `tool.result` / `tool.error`, timings |
| 131 | + |
| 132 | +--- |
| 133 | + |
| 134 | +## 4. Results (how outputs re-enter the agent) |
| 135 | + |
| 136 | +### usedTools shape |
| 137 | + |
| 138 | +```ts |
| 139 | +type UsedTool = { |
| 140 | + tool: string; // registry key / name |
| 141 | + input?: unknown; // args passed to execute |
| 142 | + output?: unknown; // success payload |
| 143 | + error?: string; // failure message |
| 144 | +}; |
| 145 | +``` |
| 146 | + |
| 147 | +### Telemetry stores (streaming / DB) |
| 148 | + |
| 149 | +| Store | Meaning | |
| 150 | +| --- | --- | |
| 151 | +| `tools.usable` | Keys available at step start | |
| 152 | +| `tools.use` / `tools.invocation` | Selected useTools (planned) | |
| 153 | +| `tools.used` / `tools.result` | Per-tool success/failure + summarized I/O | |
| 154 | +| Agent step work update | Normalized tool names for UI pipeline log | |
| 155 | + |
| 156 | +Summarization bounds large objects (`type`/`keys`) so streams stay source-safe. |
| 157 | + |
| 158 | +### Results interpolation (automatic) |
| 159 | + |
| 160 | +`injectUsedToolResultsIntoPrompt` writes prior `usedTools` to: |
| 161 | + |
| 162 | +| Prompt path | Content | |
| 163 | +| --- | --- | |
| 164 | +| `auto:tools_results` | Markdown blocks: name, status, input, truncated output/error | |
| 165 | + |
| 166 | +Sources (first match): |
| 167 | + |
| 168 | +1. `input.usedTools` |
| 169 | +2. `input.output.usedTools` |
| 170 | + |
| 171 | +Refine/Retry Thinkings therefore “see” prior tool outcomes in the system prompt |
| 172 | +hierarchy without re-parsing telemetry stores. |
| 173 | + |
| 174 | +Optional specialized formatting: `ToolPromptRegistry.formatOutput(name, output)` / |
| 175 | +`formatInput` / `formatError` (`tool:{name}:output` with fallback `tool:output`). |
| 176 | + |
| 177 | +--- |
| 178 | + |
| 179 | +## 5. PTRR placement |
| 180 | + |
| 181 | +| PTRR step | Failsafe×Thinkings | Tools postprocess | |
| 182 | +| --- | --- | --- | |
| 183 | +| Plan | yes | if `output.useTools?.length` | |
| 184 | +| Try | yes | if `output.useTools?.length` | |
| 185 | +| Refine | yes | if `output.useTools?.length` | |
| 186 | +| Retry | yes | if `output.useTools?.length` (some paths always consider tools) | |
| 187 | + |
| 188 | +Composition (simplified): |
| 189 | + |
| 190 | +```ts |
| 191 | +sequential( |
| 192 | + createFailsafeGenerationSequence({ outputSchema }), |
| 193 | + conditional( |
| 194 | + (input) => input?.output?.useTools?.length > 0, |
| 195 | + factoryToolsExecution(), |
| 196 | + (input) => input, |
| 197 | + ), |
| 198 | +); |
| 199 | +``` |
| 200 | + |
| 201 | +`ToolExecutionPrompt` holds the execute instruction (`tool:execute`) and can |
| 202 | +receive injected docs via `injectAvailableTools(docs[])`. |
| 203 | + |
| 204 | +--- |
| 205 | + |
| 206 | +## 6. Registration patterns |
| 207 | + |
| 208 | +```ts |
| 209 | +const agentExec = new AgentExecution('agent:my-agent', pipelineExecution); |
| 210 | + |
| 211 | +// Instance |
| 212 | +agentExec.tools.registerTool('bitcode.search', searchTool); |
| 213 | + |
| 214 | +// Class |
| 215 | +agentExec.tools.registerToolClass('bitcode.verify', VerifyTool); |
| 216 | + |
| 217 | +// Parent pipeline tools are visible via hierarchy getTool / getUsableTools |
| 218 | +// Optional: agentExec.tools.restrictTo(['bitcode.search']); |
| 219 | +``` |
| 220 | + |
| 221 | +Gate-aware file tools may bind `executionContext` so edits honor pipeline gates. |
| 222 | + |
| 223 | +--- |
| 224 | + |
| 225 | +## 7. Checklist for new tools |
| 226 | + |
| 227 | +1. Extend `Tool` or `ExecutionTool`; implement `use`. |
| 228 | +2. Author `@doc-code-tool` with purpose / capabilities / **parameters** / **output**. |
| 229 | +3. Ensure build-time doc-code loader runs (or `attachDocCodeToolPrompt`). |
| 230 | +4. Register under a stable string key on the agent or pipeline tools registry. |
| 231 | +5. Include `useTools` in the step/agent output schema when the LLM should select the tool. |
| 232 | +6. Read `usedTools` / stream `tools.result` for UI and proof telemetry. |
| 233 | +7. Do not bypass `factoryToolsExecution` with ad-hoc tool calls inside Reason. |
| 234 | + |
| 235 | +--- |
| 236 | + |
| 237 | +## 8. Source map |
| 238 | + |
| 239 | +| Concern | Primary source | |
| 240 | +| --- | --- | |
| 241 | +| Tool primitive | `packages/tools-generics/src/Tool.ts` | |
| 242 | +| DocCodeToolPrompt | `packages/tools-generics/src/doc-code-tool/DocCodeToolPrompt.ts` | |
| 243 | +| formatUsableTools | `packages/tools-generics/src/doc-code-tool/formatUsableTools.ts` | |
| 244 | +| AgentToolsRegistry / ExecutionTool | `packages/agent-generics/src/execution/AgentToolsRegistry.ts` | |
| 245 | +| Doc + results interpolation | `packages/agent-generics/src/execution/tool-prompt-interpolation.ts` | |
| 246 | +| factoryToolsExecution | `packages/agent-generics/src/substeps/factories.ts` | |
| 247 | +| PTRR step wiring | `packages/agent-generics/src/steps/factories.ts` | |
| 248 | +| ToolExecutionPrompt | `packages/agent-generics/src/prompts/ToolExecutionPrompt.ts` | |
0 commit comments