(invocation: ToolInvocation)
| 205 | schema = ptype.model_json_schema() |
| 206 | |
| 207 | async def wrapped_handler(invocation: ToolInvocation) -> ToolResult: |
| 208 | try: |
| 209 | # Build args based on detected signature |
| 210 | call_args = [] |
| 211 | if takes_params: |
| 212 | args = invocation.arguments or {} |
| 213 | if ptype is not None and _is_pydantic_model(ptype): |
| 214 | call_args.append(ptype.model_validate(args)) |
| 215 | else: |
| 216 | call_args.append(args) |
| 217 | if takes_invocation: |
| 218 | call_args.append(invocation) |
| 219 | |
| 220 | result = fn(*call_args) |
| 221 | |
| 222 | if inspect.isawaitable(result): |
| 223 | result = await result |
| 224 | |
| 225 | return _normalize_result(result) |
| 226 | |
| 227 | except Exception as exc: |
| 228 | # Don't expose detailed error information to the LLM for security reasons. |
| 229 | # The actual error is stored in the 'error' field for debugging. |
| 230 | return ToolResult( |
| 231 | text_result_for_llm=( |
| 232 | "Invoking this tool produced an error. " |
| 233 | "Detailed information is not available." |
| 234 | ), |
| 235 | result_type="failure", |
| 236 | error=str(exc), |
| 237 | tool_telemetry={}, |
| 238 | _from_exception=True, |
| 239 | ) |
| 240 | |
| 241 | return Tool( |
| 242 | name=tool_name, |
nothing calls this directly
no test coverage detected
searching dependent graphs…