Building Tools: Advanced Patterns
Most projects only need Building Tools. Use this page when you are writing custom capabilities and need lower-level control.Class Hierarchy
| Class | Adds | Typical use |
|---|---|---|
SimpleTool | Descriptor + result wrapper + $this->arg() | Full manual control |
ReflectiveSchemaTool | Reflective toToolSchema() from __invoke() | Auto schema from signatures |
FunctionTool | Wraps callable + cached reflective schema | Typed callable tools |
StateAwareTool | withAgentState() / $this->agentState | Read current execution state |
BaseTool | StateAwareTool + reflective schema + default metadata/instructions | State-aware class tools |
ContextAwareTool | StateAwareTool + withToolCall() / $this->toolCall | Need raw tool call context |
ContextAwareTool: Access ToolCall and State
UseContextAwareTool when you need call metadata (for tracing/correlation) in addition to state.
SimpleTool: Full Control
UseSimpleTool when you want to manage everything yourself (descriptor, schema, behavior).
Descriptors as Separate Classes
When tool docs get large, move them into a dedicated descriptor class. This keeps runtime logic short and reuses documentation cleanly.Schema Strategy Matrix
| Class | Schema source | What to do |
|---|---|---|
FunctionTool | Callable reflection (fromCallable) | Usually no override |
BaseTool | Reflection of __invoke(mixed ...$args) | Usually override toToolSchema() for explicit params |
ContextAwareTool | None by default | Implement toToolSchema() |
StateAwareTool | None by default | Implement toToolSchema() |
SimpleTool | None by default | Implement toToolSchema() |
BaseTool includes reflective schema support, but because __invoke must keep mixed ...$args, the generated schema is often too generic for production prompts.
Parameter Extraction with $this->arg()
Use $this->arg() to support named and positional arguments in one line: