Pass native tools to OpenAI completions - #7
Conversation
Propagate usable Agent tools through the typed LLM client boundary and serialize provider-native function tools for both OpenAI APIs. Add red/green coverage and a live gpt-5-nano read/edit/finish smoke. Co-authored-by: smolpaws <engel@enyst.org> Co-authored-by: openhands <openhands@all-hands.dev>
WalkthroughThe completion contract now accepts optional tool definitions. OpenAI chat and responses clients serialize those tools using provider-specific request shapes and omit the field when no tools are provided. Sequence Diagram(s)sequenceDiagram
participant LocalConversation
participant Agent
participant OpenAIClient
participant NativeTools
LocalConversation->>Agent: run conversation with tool definitions
Agent->>OpenAIClient: complete messages and usable tools
OpenAIClient-->>Agent: native tool call
Agent->>NativeTools: execute read_file or edit_file
NativeTools-->>Agent: tool observation
Agent->>OpenAIClient: complete updated conversation
OpenAIClient-->>Agent: native finish call
Agent-->>LocalConversation: finished conversation state
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces native tool support for OpenAI clients (both Chat Completions and Responses APIs). It updates the LLMClient.complete interface to accept an optional list of ToolDefinitions, modifies Agent.step() to pass only usable tools, and handles native tool serialization for OpenAI payloads while omitting the tools field when empty. The changes also include a new live example, updated documentation, and comprehensive unit tests for tool propagation and serialization. I have no feedback to provide as there are no review comments and the implementation is clean and well-tested.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Record the pinned Python Agent-to-LLM ToolDefinition contract, provider serialization ownership, preserved multi-tool dispatch, and the closed transpilation gap. Co-authored-by: smolpaws <engel@enyst.org> Co-authored-by: openhands <openhands@all-hands.dev>
Summary
LLMClient.completewith an optional typedToolDefinition[]and pass exactly the usable Agent toolstoolsfor empty requestsgpt-5-nanoread/edit/finish exampleUpstream parity
The Python Agent passes its resolved tool definitions to LLM completion. This restores that boundary in the TypeScript SDK without adding provider work outside OpenAI. Existing Anthropic, Gemini, testing, and custom clients remain source-compatible because the new argument is optional.
Agent.step()/astep()passlist(self.tools_map.values())tomake_llm_completion()/amake_llm_completion()Agent.step()passesthis.tools.filter(tool => tool.usable)toLLMClient.complete()src/agent/__tests__/tool-propagation.test.tsToolDefinitions and excludes definitions marked unusable; no server-only shimmake_llm_completion(..., tools)routes the same definitions to completion or ResponsesLLMClient.complete(messages, tools?)is the thin shared boundarytoolsLLM._finalize_completion_params()/_finalize_responses_params()callToolDefinition.to_openai_tool()/to_responses_tool()ToolDefinition.toResponsesTool()and wrap only the Chat function shapesrc/llm/__tests__/openai-client.test.tsstrict: false; Anthropic/Gemini expansion remains out of scopedispatchLlmResponse()preserves every call;ParallelToolExecutorexecutes batches in input orderresponse-dispatch.test.ts;parallel-executor.test.ts; live read/edit/finish smokeValidation
npm test— 244/244 passednpm run typechecknpm run lintnpm run buildnpm run typecheck:examplesnpm run test:examplesnpm run typecheck:livenpm pack --dry-runnpm run live:openai-tools—gpt-5-nanoemitted native actionsread_file,edit_file,read_file,finish; executors ran and the file mutation was verifiedLive workflow
Label this PR
test-examplesto run the example suite withOPENAI_API_KEYfrom the existingexamplesGitHub Environment. No credential values are printed.This pull request was created by an AI agent (OpenHands) on behalf of Engel Nyst.
Summary by CodeRabbit
live:openai-toolscommand to run it.