- Introduction
- Getting Started with UiPath Agents
- Getting Started with UiPath Agents using LangGraph
- Building a Low-Code Agent in Studio Web
- Adding Tools to Your UiPath Agent
- Getting Started with UiPath Maestro Flow
Use your coding agent and UiPath skills to add a tool to the LangGraph agent.
Step 7 - Add a live lookup tool
Right now the agent is guessing from vibes: nothing it says about a dragon or a goblin is checked against anything real. To improve the accuracy of the classifier, let's add a tool to verify quest information before finalizing a tier recommendation. To do this, the tool will use the Open5e API to search for creatures published under the 5e System Reference Document (SRD).
This is standard LangGraph, not a UiPath-specific trick: a plain Python function decorated with @tool, bound to the model, and the model decides at runtime whether calling it is worth it. Your coding agent wires up that binding syntax for you.
Ask your coding agent:
Update main.py to add one Python tool to the existing LangGraph agent: a function that looks up a monster's challenge rating from the Open5e SRD API and uses it to inform the difficulty tier.
Tool behavior:
- Query GET https://api.open5e.com/v2/creatures/ using the `requests` library (already available as a transitive dependency; add it directly with `uv add requests` only if the import fails), with query parameters: name__icontains=<creature name or type the model supplies>, document__key__in=srd-2024, limit=10, fields=key,name,type,size,challenge_rating,alignment
- Set a 10-second timeout on the request, and call raise_for_status() before reading the response body — this is a live external API call, so it should fail fast with a clear error instead of hanging or raising a confusing KeyError if Open5e is slow or returns a non-200 response.
- If the response has zero results, return that as-is — nothing further to do.
- If the response has more than one result, return the full list and let the agent pick the best match rather than guessing which one is correct.
- Bind the tool with the standard LangChain @tool decorator. Let the model decide when to call it based on the tool's description — don't force a call on every input.
- Name the tool function `get_challenge_rating`.
- In the tool's docstring, describe what counts as a creature in the abstract — don't include a named example creature (e.g., avoid phrasing like "e.g. goblin, young red dragon"). A concrete example name in the docstring can get echoed back by the model as a spurious lookup for a creature that isn't actually in the quest.
Update the system prompt so that:
- The agent calls this tool whenever the quest description names or strongly implies a specific creature.
- Only call the tool for creatures explicitly named or strongly implied in the quest description — never for other creatures used as a comparison or reference point.
- When a `challenge_rating` comes back, the agent uses it to inform the tier classification and cites it explicitly in the `reasoning` output field. Do not fabricate or guess a challenge rating from memory — only cite one that actually came from the tool's response.
- If no tool call happens, or the tool returns zero results, the agent classifies using its existing judgment, same as before.
- Don't add new output fields. The State schema stays `tier` and `reasoning` only — the challenge rating goes into the reasoning text, not a new field.
Only touch main.py.
Don't run any uip codedagent commands or otherwise verify that the agent runs — I will do this myself.
Update main.py to add one Python tool to the existing LangGraph agent: a function that looks up a monster's challenge rating from the Open5e SRD API and uses it to inform the difficulty tier.
Tool behavior:
- Query GET https://api.open5e.com/v2/creatures/ using the `requests` library (already available as a transitive dependency; add it directly with `uv add requests` only if the import fails), with query parameters: name__icontains=<creature name or type the model supplies>, document__key__in=srd-2024, limit=10, fields=key,name,type,size,challenge_rating,alignment
- Set a 10-second timeout on the request, and call raise_for_status() before reading the response body — this is a live external API call, so it should fail fast with a clear error instead of hanging or raising a confusing KeyError if Open5e is slow or returns a non-200 response.
- If the response has zero results, return that as-is — nothing further to do.
- If the response has more than one result, return the full list and let the agent pick the best match rather than guessing which one is correct.
- Bind the tool with the standard LangChain @tool decorator. Let the model decide when to call it based on the tool's description — don't force a call on every input.
- Name the tool function `get_challenge_rating`.
- In the tool's docstring, describe what counts as a creature in the abstract — don't include a named example creature (e.g., avoid phrasing like "e.g. goblin, young red dragon"). A concrete example name in the docstring can get echoed back by the model as a spurious lookup for a creature that isn't actually in the quest.
Update the system prompt so that:
- The agent calls this tool whenever the quest description names or strongly implies a specific creature.
- Only call the tool for creatures explicitly named or strongly implied in the quest description — never for other creatures used as a comparison or reference point.
- When a `challenge_rating` comes back, the agent uses it to inform the tier classification and cites it explicitly in the `reasoning` output field. Do not fabricate or guess a challenge rating from memory — only cite one that actually came from the tool's response.
- If no tool call happens, or the tool returns zero results, the agent classifies using its existing judgment, same as before.
- Don't add new output fields. The State schema stays `tier` and `reasoning` only — the challenge rating goes into the reasoning text, not a new field.
Only touch main.py.
Don't run any uip codedagent commands or otherwise verify that the agent runs — I will do this myself.
Why this prompt is so specific. As in Step 5, the file scoping and the instruction not to run or verify anything is deliberate: the next commands in this lab exercise the tool directly, so verification is left to you.
As you adapt the prompt to your own work, you are again advised to remove the last two sentences to fully enable your coding agent to exercise your code.
Coding agents are non-deterministic. Your generated tool code will differ from any examples shown here; that is expected. What matters is that main.py still runs without errors and calls the tool only when a creature is named.
This tool does not add or change any input or output fields, so there is no need to re-run uip codedagent init this time. Only re-run it when your Input/Output models change.
Re-run the dragon example from Step 6:
uip codedagent run agent '{"description": "Slay the ancient red dragon terrorizing the countryside"}'
uip codedagent run agent '{"description": "Slay the ancient red dragon terrorizing the countryside"}'
Watch the trace this time: the agent calls the SRD lookup, gets back a real challenge rating, and cites it in its reasoning instead of just asserting Legendary. That's the difference between a text classifier and an agent that can go verify itself.
With the tool wired in, you are ready to test that the agent uses it correctly and scores well across a range of inputs.