Tool-selection capability interfaces, and Agent support for toolChoice and effort - #29
Merged
Merged
Conversation
…ce and effort from Agent Adds ToolSelectableInterface and NamedToolSelectableInterface, so callers can ask what a provider can enforce instead of catching a ProviderException. NamedToolSelectableInterface extends the other because forcing a named tool is strictly more than forcing some tool, which makes the common case one check. Capability by type matches how Embedding, Image and Video already work. Agent can now pass toolChoice and effort, neither of which it could reach before. They differ on purpose: a forced tool applies to the opening call only, because forcing one every turn leaves the model unable to answer in plain text and the loop can only end by exhausting maxTurns. Effort applies throughout, which is what asking to think harder means.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Capability by type, not by probe
Adds
ToolSelectableInterface(can forcerequired/none) andNamedToolSelectableInterface extendsit (can also force one named tool). Callers ask before calling instead of catching:extendsrather than siblings, because forcing a named tool is strictly more than forcing a tool, so the common case is one check. This matches howEmbedding/Image/Videocapabilities already work.supportsTool()does not answer this question: it returnstrueon both Ollama and Cohere, which throw on forced choice.FailoverProviderdeliberately implements neither. Its capability depends on the providers it holds at runtime, andinstanceofis fixed at class definition, so claiming a capability it might not honour would be worse than claiming none.Agent can now reach both options
Agentcould set neithertoolChoicenoreffort, which made both unreachable from the high-level API.They behave differently, on purpose:
toolChoiceforces the opening call only. Applying it every turn leaves the model unable to answer in plain text, so the loop could only ever end by exhaustingmaxTurnsand throwing. There is a test asserting call 0 carries it and call 1 does not.effortapplies to every turn, which is what asking to think harder means.Compatibility
Purely additive: two new interfaces, two new option keys read from an array callers already pass.
ProviderInterfaceuntouched, no signature changed. Shipping as a patch so everything on^0.15picks it up with no re-tagging.252 tests, Psalm clean, 88% coverage.