π οΈ Tool: Custom Python Code π οΈ
Give your Ollama Agent a custom tool you write yourself
- my_ext_var
- my_ext_var_2
- my_ext_var_3
- tool
Web search and file reading cover the obvious cases, but sooner or later you want your OllamaAgent to do something specific to your own workflow - call an internal API, do some math the model is bad at, look something up in a format nothing else in the pack handles. This node is the escape hatch: you write a plain Python function with a docstring, and it becomes a tool the agent can call by name, with the docstring's Args section telling the model what arguments to pass and why.
It's the most powerful node in the pack and also the one to treat with the most care, for a plain reason: the code in python_code actually executes on your machine when the agent decides to call it. This isn't a sandboxed or restricted environment - it's your Python interpreter, running whatever you wrote. Custom nodes in ComfyUI generally run with full user-level access already (that's true of everything you install, not something specific to this pack), but this node is the one place in the whole pack where you are directly writing the executable code yourself, so it's worth being deliberate about what goes in it - same as you'd be careful pasting any Python from a workflow file you didn't write yourself into a node like this.
How it works
You write a function - the default example is custom_tool(text: str) -> str, with a docstring describing what it does and what its Args mean. The agent reads that docstring to decide when and how to call the function, then the node executes it and feeds the return value back into the agent's reasoning. The tool_name you set is what the agent sees; if you leave it as the default custom_python_tool, the node falls back to using the function name actually defined in your code instead.
The standout feature is my_ext_var: connect any node's output to it, and that value becomes a global variable available inside your Python function by that exact name - the default example code references my_ext_var directly inside the function body. That means you can pull live data from elsewhere in your ComfyUI graph (a generated prompt, an image path, a value from another node) into a tool the agent calls, without hardcoding it into the function text.
The inputs and outputs that matter
tool_name(defaultcustom_python_tool) - the name the agent calls this by, falling back to your function's actual name if left default.python_code(multiline) - your function. Follow the pattern in the default: a real docstring with anArgs:section, since that's what the agent reads to know what to pass.my_ext_var,my_ext_var_2,my_ext_var_3(all optional, accept any type*) - up to three external values wired in from elsewhere in your graph, available as plain variables inside the function body by those exact names.
Output is a single tool value, type OLLAMA_TOOL - wire it into OllamaAgent's tools input directly, or combine it with other tools via OllamaToolCombine.
How to install it
Bundled with the rest of the pack. Via ComfyUI Manager, search "ComfyUI-Ollama-Describer" and install. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/alisson-anjos/ComfyUI-Ollama-Describer.git
pip install -r requirements.txt # or install.bat on Windows
Restart ComfyUI. Needs Ollama running with a tool-calling-capable model, same as every other tool node here.
Common issues & troubleshooting
If the agent never calls your function, check the docstring first - a vague or missing Args: description is the most common reason a model fails to figure out when or how to use a custom tool, much more often than the model itself being incapable. If the tool call errors out, that's your function raising an exception, same as running the code directly - test it outside the agent loop first if you're not sure it's correct. And keep in mind arguments the function receives at call time are chosen by the LLM based on the conversation, not typed by you - if your function does anything consequential (writes files, calls an API, touches data), write it defensively, the same way you'd write any function whose inputs you don't fully control.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| tool_name | STRING | custom_python_tool | The name of the tool as seen by the Agent. If left as 'custom_python_tool', it will try to use the function name defined in the code. |
| python_code | STRING | def custom_tool(text: str) -> str: """A helpful description of what this does. Args: text: input text Returns: a useful string """ return f"Processed: {text} | {my_ext_var}" | β |
| my_ext_varopt | * | Connect ANY node output here and it will be available as a variable inside your python code! | |
| my_ext_var_2opt | * | Another external variable | |
| my_ext_var_3opt | * | Another external variable |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| tool | OLLAMA_TOOL | β |