Skip to content

## Weather Bot Agent Example with FunctionTool#119

Open
muscodev wants to merge 5 commits intojentic:mainfrom
muscodev:example/weatherbot
Open

## Weather Bot Agent Example with FunctionTool#119
muscodev wants to merge 5 commits intojentic:mainfrom
muscodev:example/weatherbot

Conversation

@muscodev
Copy link
Contributor

@muscodev muscodev commented Oct 10, 2025

Added a weather bot agent example demonstrating the new FunctionTool feature for converting Python functions into agent tools.
Related to #82

What's New

  • Weather bot CLI and web interface using OpenWeather API
  • FunctionTool implementation with automatic schema extraction from type hints
  • Support for both sync and async functions
  • Keyword-based tool discovery for agent systems

Files Added

  • examples/weather_bot/ - Complete weather bot example
  • app/tools_base.py - FunctionTool and FunctionToolProvider implementation
  • app/agent.py - CLI agent with tool integration
  • app/bot.py - FastAPI web interface

tools creation

Implimented a decorator pattern

func_tools = FunctionToolProvider()


@func_tools.tool(["weather", "temperature", "humidity", "forecast"])
async def get_weather(lat: float, lon: float, units: str = "metric") -> dict:
    """
    Retrieve real-time weather information for a specific geographic location.
    location can be found using get_coordinate_by_city or get_coordinate_by_zip tools
    """
    url = "http://api.openweathermap.org/data/2.5/weather"
    params = {"lat": lat, "lon": lon, "appid": API_KEY, "units": units}

    async with httpx.AsyncClient() as client:
        resp = await client.get(url, params=params)
        data = resp.json()

    if resp.status_code != 200:
        return {"error": data.get("message", "Failed to fetch weather")}

    return {
        "city": data["name"],
        "temp": data["main"]["temp"],
        "humidity": data["main"]["humidity"],
        "feels_like": data["main"]["feels_like"],
        "weather": data["weather"][0]["description"],
        "wind_speed": data["wind"]["speed"],
    }

Summary by CodeRabbit

  • New Features

    • Added Weather Bot example with command-line interface and interactive web chat for weather information
    • Integrated real-time weather tools supporting queries across multiple LLM models
  • Documentation

    • Added comprehensive getting started guide with detailed setup and usage instructions
    • Included environment configuration template with required API keys and model settings
  • Tests

    • Added function tool system test coverage

✏️ Tip: You can customize this high-level summary in your review settings.

@muscodev muscodev requested a review from a team as a code owner October 10, 2025 19:28
@muscodev
Copy link
Contributor Author

Question: Should FunctionTool be moved to core?

Currently, I've implemented FunctionTool in examples/weather_bot/app/tools_base.py as part of the example.

However, this functionality seems generally useful for the entire framework. Would it make sense to move it to agents/tools/function.py as a core feature?

Happy to refactor and create a separate PR for this if you think it's a good fit for the core library.
Thoughts? @rodjentic

@muscodev
Copy link
Contributor Author

here is a small screenshot from exaample
image

@muscodev
Copy link
Contributor Author

Hi @rishikesh-jentic,
Just a gentle reminder on my PR — please let me know if any updates are needed. Thanks!

@rishikesh-jentic
Copy link
Collaborator

@CodeRabbit review this PR

@coderabbitai
Copy link

coderabbitai bot commented Jan 14, 2026

@rishikesh-jentic: I'll review the PR changes now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a complete weather bot example application featuring an agent-based system with tool integration, supporting both CLI and web interfaces via FastAPI. It includes environment configuration, tool infrastructure for wrapping Python functions, OpenWeather API integration, and comprehensive tests.

Changes

Cohort / File(s) Summary
Configuration & Documentation
examples/weather_bot/.env_sample, examples/weather_bot/requirements.txt, examples/weather_bot/README.md
New environment template with API key placeholders; dependency list (httpx, python-dotenv, pytest, fastapi[standard]); comprehensive documentation covering installation, configuration, usage patterns, and project structure.
Core Agent Setup
examples/weather_bot/app/agent.py
Initializes weather_agent by composing LiteLLM, DictMemory, ReACTReasoner, and weather_tools into a StandardAgent instance with configured token limits and turn constraints.
Tool Infrastructure
examples/weather_bot/app/tools_base.py
New framework introducing FunctionTool and FunctionToolProvider classes for wrapping Python callables with metadata extraction, parameter validation, keyword-based search, and automatic async/sync execution routing.
Weather Tools
examples/weather_bot/app/weather_tools.py
Three exported tools wrapping OpenWeather APIs: get_weather() (current conditions), get_coordinate_by_city() (forward geocoding), and get_coordinate_by_zip() (ZIP code lookup) with async HTTP requests and error handling.
User Interfaces
examples/weather_bot/app/bot.py, examples/weather_bot/app/cli_bot.py
FastAPI web service exposing /ask (query endpoint), / (root), and /chat (HTML UI with interactive messaging); CLI module with interactive prompt loop, goal reading, and formatted result output.
Tests
examples/weather_bot/tests/test_function_tool.py
Comprehensive test suite covering tool registration, docstring validation, parameter schema extraction, keyword/content-based search, and both sync/async tool execution.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Interface as Web/CLI Interface
    participant Agent as Weather Agent
    participant Reasoner as ReACT Reasoner
    participant ToolProvider as Tool Provider
    participant Weather as Weather Tools
    participant LLM as LiteLLM

    User->>Interface: Submit query/goal
    Interface->>Agent: solve(goal)
    Agent->>Reasoner: reason(goal)
    loop Reasoning Loop
        Reasoner->>LLM: Generate thought/action
        LLM-->>Reasoner: Thought or Tool Use
        alt Use Tool
            Reasoner->>ToolProvider: execute(tool, params)
            ToolProvider->>Weather: Call tool function
            Weather-->>ToolProvider: Result
            ToolProvider-->>Reasoner: Execution result
        else Final Answer
            Reasoner-->>Agent: Answer
        end
    end
    Agent-->>Interface: ReasoningResult
    Interface-->>User: Formatted response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A weather bot hops into view,
With tools that fetch the skies so blue!
Web and CLI paths aligned,
Agents reasoning, well-designed—
Where it rains and how it blows,
Our fluffy bot forever knows! 🌤️

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.95% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a weather bot example that demonstrates the new FunctionTool feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🤖 Fix all issues with AI agents
In `@examples/weather_bot/app/agent.py`:
- Around line 12-13: The llm setup uses LiteLLM with max_tokens=50 which will
truncate weather answers; update the llm initialization (variable llm and
constructor LiteLLM) to use a much larger token budget (e.g., 200–500) or make
max_tokens configurable from an environment variable, and also pass the model
explicitly by reading an LLM_MODEL env var (or default) into the LiteLLM
constructor so the chosen model is used rather than relying on defaults.

In `@examples/weather_bot/app/bot.py`:
- Around line 213-220: The addMessage function is vulnerable because it sets
msg.innerHTML with unsanitized text; change the implementation to avoid
innerHTML by creating the bubble element via document.createElement('div') (or
similar) and set its textContent (or append a text node) for the message body
instead of interpolating into HTML, and ensure both the user-provided text and
any bot responses are treated as plain text (or passed through a sanitizer)
before inserting into the DOM; update references to msg.innerHTML and the bubble
creation in addMessage accordingly.
- Around line 40-42: The response string returned by the GET handler decorated
with `@app.get` in the function root uses a curly right single quotation mark;
replace that curly quote in the message "🤖 Hi! I’m WeatherBot. Use POST /ask
with {query: 'your question'}" with a standard ASCII apostrophe so the string
uses "I'm" and the inner quotes are standard single quotes for "your question";
update the literal in root to use straight ASCII quotes.

In `@examples/weather_bot/app/cli_bot.py`:
- Around line 38-52: The welcome print in main() contains grammatical and
typographical errors; update the string passed to print() (the welcome message
in main) to a clear, grammatically correct greeting such as a single sentence
that capitalizes properly, removes extra commas, and introduces the bot (e.g.,
"Hi! Welcome — I am WeatherBot. Ask me anything about the weather."). Ensure you
edit the print call inside main() that currently prints the malformed welcome
message.

In `@examples/weather_bot/app/tools_base.py`:
- Around line 117-120: The ValueError message in load (FunctionTool) has typos;
update the raise to use correct wording and punctuation (e.g., "function tool
doesn't have '{tool}' definition" or similar) so the message reads clearly;
change the string in the raise inside load that checks getattr(tool, 'id', None)
not in self._tools to the corrected text.

In `@examples/weather_bot/app/weather_tools.py`:
- Around line 63-64: Update the misleading error text in the status check where
resp and data are used: replace the "Failed to fetch weather" default message
with something accurate like "Failed to fetch coordinates" (keep using
data.get("message", "...") to surface API errors). Locate the conditional that
reads if resp.status_code != 200: return {"error": data.get("message", "Failed
to fetch weather")} and change the default string to reflect coordinates
fetching.
- Around line 52-54: The function get_coordinate_by_city currently has a
misplaced Annotated and an unused test parameter; remove the unused parameter
(test: bool = True) and apply the Annotated only to the city parameter with a
correct description (e.g., Annotated[str, "city name"]) so the signature becomes
a single-parameter async function; update any call sites that pass the
now-removed test argument accordingly.
- Around line 94-95: The error return uses a generic/incorrect default message;
change the default error text to accurately describe this operation (e.g.,
"Failed to fetch weather for provided coordinates" or similar) in the function
that contains the snippet (the same function pair as
get_coordinate_by_city—update the return in the block with resp.status_code !=
200 to use the new descriptive default message while still preferring
data.get("message", ...)). Ensure the message clearly mentions
weather-by-coordinates so it isn't misleading.
- Line 11: API_KEY is set from the environment but not validated, so it may be
None and cause silent auth failures; update the module to fail fast by
validating API_KEY after it’s loaded (the API_KEY symbol) and raise a clear
RuntimeError or log+exit if missing. Alternatively, if you need module import
without the key, add a helper like ensure_api_key_or_raise() and call it at the
start of each tool function that uses API_KEY (e.g., in any
get_weather()/fetch_forecast() functions) to perform the same check before
making API calls.

In `@examples/weather_bot/README.md`:
- Around line 113-121: The README contains a fenced code block without a
language specifier; update the block delimiter in examples/weather_bot/README.md
to include a language (e.g., change ``` to ```text or ```bash/```tree) so the
code fence declares its language for MD040 linting; edit the specific fenced
block that lists the project tree and replace its opening backticks with a
language-tagged opening backtick sequence.
- Line 124: The image reference in the README uses the misspelled directory
"screenshorts" instead of "screenshots"; update the image path in the Markdown
(the line containing "![alt text](screenshorts/image.png)") to "![alt
text](screenshots/image.png)" and verify the file exists at that corrected path,
also search the README for any other occurrences of "screenshorts" and correct
them to "screenshots".
- Around line 81-83: Remove the leading indentation before the command inside
the README's fenced code block so the line reads exactly `python -m app.cli_bot`
(no leading spaces) to avoid markdown rendering issues; update the code block
content where the command appears to ensure the backticks remain on their own
lines and the command line has no preceding whitespace.
- Around line 93-94: The README contains a code block line with a leading space
before the command "fastapi run app/bot.py"; remove the leading whitespace so
the command starts at column 0 (i.e., change "        fastapi run app/bot.py" to
"fastapi run app/bot.py") to ensure correct rendering and copy-paste behavior in
the examples/weather_bot README.
- Around line 97-98: The README currently uses bare URLs on the lines starting
with "**Local**" and "**API Docs**"; replace those bare URLs with proper
Markdown link syntax by turning the labels into link text that points to their
respective URLs (e.g., use the "Local" label as the link text for
http://localhost:8000/chat and "API Docs" as the link text for
http://localhost:8000/docs) so the entries use [label](url) style links instead
of plain URLs.
- Line 4: The markdown image path contains a typo: update the markdown line
referencing the image (the token "! [bot](screenshorts/bot.png)" in README) to
use the correct folder name "screenshots" so it reads "!
[bot](screenshots/bot.png)" (or rename the directory to match the typo),
ensuring the image renders correctly.
🧹 Nitpick comments (8)
examples/weather_bot/requirements.txt (1)

1-4: Consider pinning dependency versions for reproducibility.

Unpinned dependencies can lead to inconsistent behavior across environments. While acceptable for an example project, consider pinning at least major versions (e.g., httpx>=0.27,<1.0) to prevent unexpected breakages.

Also, pytest is a dev/test dependency—consider separating it into a requirements-dev.txt or using [dev] extras in a pyproject.toml.

Suggested improvements
-httpx
-python-dotenv
-pytest
-fastapi[standard]
+httpx>=0.27
+python-dotenv>=1.0
+fastapi[standard]>=0.115

And create a separate requirements-dev.txt:

pytest>=8.0
examples/weather_bot/.env_sample (1)

1-3: Use standard placeholder format for API keys.

The placeholder text "replace with yours" contains spaces which could cause parsing issues if accidentally used. Consider using a more standard format.

Suggested format
-OPENWEATHER_API_KEY=replace with yours
-GEMINI_API_KEY=replace with yours
-OPENAI_API_KEY=replace with yours
+OPENWEATHER_API_KEY=your_openweather_api_key_here
+GEMINI_API_KEY=your_gemini_api_key_here
+OPENAI_API_KEY=your_openai_api_key_here
examples/weather_bot/tests/test_function_tool.py (1)

29-36: Test is functional but couples to internal structure.

Accessing provider._tools directly works but ties the test to implementation details. Consider adding a public method like get_tool(name) to FunctionToolProvider if this pattern is needed frequently.

The exact string assertion on line 35 is somewhat brittle—if summary formatting changes, this test will break.

examples/weather_bot/app/cli_bot.py (2)

5-19: Simplify exception handling.

The except (EOFError, KeyboardInterrupt): raise block is redundant since exceptions propagate automatically. The static analyzer flagged this with TRY203.

♻️ Suggested simplification
 def read_user_goal(prompt: str = "🤖 Enter your goal: ") -> str:
     """Read a goal from user input via stdin."""
     print(prompt, end="", flush=True)
-    try:
-        line = sys.stdin.readline()
-        if not line:  # EOF
-            raise KeyboardInterrupt
-
-        goal = line.strip()
-        if goal.lower() in {"bye", "quit", "exit", "q"}:
-            raise KeyboardInterrupt
-
-        return goal
-    except (EOFError, KeyboardInterrupt):
-        raise
+    line = sys.stdin.readline()
+    if not line:  # EOF
+        raise KeyboardInterrupt
+
+    goal = line.strip()
+    if goal.lower() in {"bye", "quit", "exit", "q"}:
+        raise KeyboardInterrupt
+
+    return goal

22-35: Consider adding type hint for result parameter.

The function works correctly with ReasoningResult. Adding a type hint would improve clarity and enable better IDE support.

♻️ Suggested type hint
+from agents.reasoner.base import ReasoningResult
+
-def print_result(result) -> None:
+def print_result(result: ReasoningResult) -> None:
examples/weather_bot/app/tools_base.py (1)

54-59: Add stacklevel to warning for better debugging.

The warning will point to this internal line rather than the caller's registration site. Adding stacklevel=2 helps users identify which function lacks a docstring.

♻️ Suggested fix
         if not func.__doc__:
             warnings.warn(
                 f"Functiontool '{func.__name__}' has no docstring. "
-                "Please add one — the first 2 lines will be used as summary."
+                "Please add one - the first 2 lines will be used as summary.",
+                stacklevel=2
             )
examples/weather_bot/app/bot.py (2)

29-37: Consider handling result.success == False case.

The endpoint always returns final_answer regardless of success status. Failed queries might benefit from different handling (e.g., different HTTP status code or error field).

♻️ Optional enhancement
 `@app.post`("/ask")
 async def ask_bot(input: QueryRequest):
     query = BOT_PROMPT.format(user_query=input.query)
     result: ReasoningResult = await asyncio.to_thread(
         weather_agent.solve,
         query,
     )
 
-    return {"response": str(result.final_answer)}
+    if result.success:
+        return {"response": str(result.final_answer)}
+    else:
+        return {"response": str(result.final_answer), "success": False}

47-48: Consider extracting HTML to a template file.

The 200-line inline HTML string is harder to maintain and test. Consider using FastAPI's Jinja2Templates or serving a static HTML file.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3b76b3 and 1195a21.

⛔ Files ignored due to path filters (2)
  • examples/weather_bot/screenshorts/bot.png is excluded by !**/*.png
  • examples/weather_bot/screenshorts/image.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • examples/weather_bot/.env_sample
  • examples/weather_bot/README.md
  • examples/weather_bot/app/__init__.py
  • examples/weather_bot/app/agent.py
  • examples/weather_bot/app/bot.py
  • examples/weather_bot/app/cli_bot.py
  • examples/weather_bot/app/tools_base.py
  • examples/weather_bot/app/weather_tools.py
  • examples/weather_bot/requirements.txt
  • examples/weather_bot/tests/test_function_tool.py
🧰 Additional context used
🧬 Code graph analysis (5)
examples/weather_bot/tests/test_function_tool.py (1)
examples/weather_bot/app/tools_base.py (3)
  • FunctionTool (47-84)
  • FunctionToolProvider (87-135)
  • tool (91-102)
examples/weather_bot/app/agent.py (5)
agents/standard_agent.py (1)
  • StandardAgent (36-149)
agents/llm/litellm.py (1)
  • LiteLLM (10-142)
agents/memory/dict_memory.py (1)
  • DictMemory (10-26)
examples/discord/discord_agent.py (1)
  • reasoner (118-139)
agents/reasoner/react.py (1)
  • ReACTReasoner (19-179)
examples/weather_bot/app/tools_base.py (1)
agents/tools/base.py (2)
  • ToolBase (7-30)
  • JustInTimeToolingBase (32-48)
examples/weather_bot/app/bot.py (2)
agents/reasoner/base.py (1)
  • ReasoningResult (12-20)
agents/standard_agent.py (1)
  • solve (88-125)
examples/weather_bot/app/cli_bot.py (1)
agents/standard_agent.py (1)
  • solve (88-125)
🪛 markdownlint-cli2 (0.18.1)
examples/weather_bot/README.md

97-97: Bare URL used

(MD034, no-bare-urls)


98-98: Bare URL used

(MD034, no-bare-urls)


113-113: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff (0.14.11)
examples/weather_bot/app/weather_tools.py

53-53: Unused function argument: test

(ARG001)

examples/weather_bot/app/tools_base.py

55-55: No explicit stacklevel keyword argument found

Set stacklevel=2

(B028)


66-66: Docstring contains ambiguous (EN DASH). Did you mean - (HYPHEN-MINUS)?

(RUF002)


119-119: Avoid specifying long messages outside the exception class

(TRY003)

examples/weather_bot/app/bot.py

42-42: String contains ambiguous (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?

(RUF001)

examples/weather_bot/app/cli_bot.py

11-11: Abstract raise to an inner function

(TRY301)


15-15: Abstract raise to an inner function

(TRY301)


17-17: Consider moving this statement to an else block

(TRY300)


18-19: Remove exception handler; error is immediately re-raised

(TRY203)

🔇 Additional comments (12)
examples/weather_bot/app/agent.py (1)

15-27: Agent wiring looks correct.

The StandardAgent is properly composed with LiteLLM, DictMemory, ReACTReasoner, and the weather tools. The component integration follows the expected patterns from the framework.

examples/weather_bot/tests/test_function_tool.py (3)

1-25: Test setup and dummy functions look good.

The dummy functions provide good coverage scenarios: sync with docstring, async with docstring, and sync without docstring. The type hints are properly defined for schema extraction testing.


90-95: Async test works but relies on internal asyncio.run.

The test validates async execution correctly. Note that provider.execute internally calls asyncio.run(), which works here but would fail if called from within an already-running event loop. For more robust async testing, consider using pytest-asyncio with @pytest.mark.asyncio.


98-102: Good coverage of error path.

This test correctly validates that loading an unregistered tool raises ValueError.

examples/weather_bot/app/cli_bot.py (1)

1-2: LGTM!

Imports are clean and minimal.

examples/weather_bot/app/weather_tools.py (1)

14-37: LGTM!

The function correctly fetches weather data, handles errors, and returns a well-structured response.

examples/weather_bot/app/tools_base.py (4)

18-23: LGTM!

The parse_annotation helper correctly extracts base type and metadata from Annotated types.


26-44: LGTM!

The extract_param_info function correctly builds parameter metadata from function signatures and type hints.


61-84: LGTM!

The FunctionTool methods correctly implement the ToolBase interface, providing keywords, summary, details, and parameter schema extraction.


130-135: The current usage pattern is safe due to asyncio.to_thread(), but the execute() method has a fragile API design.

While the FastAPI integration in bot.py correctly uses await asyncio.to_thread(weather_agent.solve, query) to run the synchronous reasoning loop in a separate thread (avoiding event loop conflicts), the underlying execute() method remains error-prone. If integrated directly into an async context without asyncio.to_thread(), it would immediately fail with RuntimeError: This event loop is already running.

Consider restructuring to provide a separate async def execute_async() method that can be called from async contexts, or add robust loop detection to prevent misuse:

async def execute_async(self, tool: FunctionTool, parameters: Dict[str, Any]) -> Any:
    """Async execution - use this when already in an async context."""
    if inspect.iscoroutinefunction(tool.func):
        return await self._execute_async(tool, parameters)
    return self._execute_sync(tool, parameters)
examples/weather_bot/app/bot.py (2)

1-9: LGTM!

Imports and FastAPI app initialization are appropriate. Using asyncio.to_thread for the blocking solve() call is the correct pattern.


11-22: BOT_PROMPT is actively used in the /ask endpoint.

The prompt is formatted with the user query and passed directly to weather_agent.solve(). The current implementation wraps the user input with the prompt template before sending it to the agent, so the prompt is serving its intended purpose.

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +12 to +13
# try changing to you own prefered model and add the API key in the .env file/ environment variable
llm = LiteLLM(max_tokens=50)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

max_tokens=50 is likely too restrictive for weather responses.

A 50-token limit will severely truncate most LLM responses. Weather descriptions, forecasts, and conversational replies typically require 200-500+ tokens. This will cause incomplete or cut-off answers.

Additionally, the comment mentions changing the model, but no model parameter is passed to LiteLLM. Ensure LLM_MODEL is read from the environment or pass it explicitly.

Proposed fix
+import os
+
 # try changing to you own prefered model and add the API key in the .env file/ environment variable
-llm = LiteLLM(max_tokens=50)
+llm = LiteLLM(model=os.getenv("LLM_MODEL"), max_tokens=1024)
🤖 Prompt for AI Agents
In `@examples/weather_bot/app/agent.py` around lines 12 - 13, The llm setup uses
LiteLLM with max_tokens=50 which will truncate weather answers; update the llm
initialization (variable llm and constructor LiteLLM) to use a much larger token
budget (e.g., 200–500) or make max_tokens configurable from an environment
variable, and also pass the model explicitly by reading an LLM_MODEL env var (or
default) into the LiteLLM constructor so the chosen model is used rather than
relying on defaults.

Comment on lines +213 to +220
function addMessage(text, sender) {
const chat = document.getElementById('chat');
const msg = document.createElement('div');
msg.className = `message ${sender}`;
msg.innerHTML = `<div class="bubble">${text}</div>`;
chat.appendChild(msg);
chat.scrollTop = chat.scrollHeight;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

XSS vulnerability: user and bot messages inserted via innerHTML without sanitization.

Both user input and bot responses are directly interpolated into HTML using innerHTML. If the bot response contains HTML or JavaScript (e.g., from a compromised API or unexpected data), it will execute in the user's browser.

🔒 Suggested fix using `textContent`
 function addMessage(text, sender) {
   const chat = document.getElementById('chat');
   const msg = document.createElement('div');
   msg.className = `message ${sender}`;
-  msg.innerHTML = `<div class="bubble">${text}</div>`;
+  const bubble = document.createElement('div');
+  bubble.className = 'bubble';
+  bubble.textContent = text;
+  msg.appendChild(bubble);
   chat.appendChild(msg);
   chat.scrollTop = chat.scrollHeight;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function addMessage(text, sender) {
const chat = document.getElementById('chat');
const msg = document.createElement('div');
msg.className = `message ${sender}`;
msg.innerHTML = `<div class="bubble">${text}</div>`;
chat.appendChild(msg);
chat.scrollTop = chat.scrollHeight;
}
function addMessage(text, sender) {
const chat = document.getElementById('chat');
const msg = document.createElement('div');
msg.className = `message ${sender}`;
const bubble = document.createElement('div');
bubble.className = 'bubble';
bubble.textContent = text;
msg.appendChild(bubble);
chat.appendChild(msg);
chat.scrollTop = chat.scrollHeight;
}
🤖 Prompt for AI Agents
In `@examples/weather_bot/app/bot.py` around lines 213 - 220, The addMessage
function is vulnerable because it sets msg.innerHTML with unsanitized text;
change the implementation to avoid innerHTML by creating the bubble element via
document.createElement('div') (or similar) and set its textContent (or append a
text node) for the message body instead of interpolating into HTML, and ensure
both the user-provided text and any bot responses are treated as plain text (or
passed through a sanitizer) before inserting into the DOM; update references to
msg.innerHTML and the bubble creation in addMessage accordingly.

Comment on lines +38 to +52
def main():
# Step 4: Use your custom agent
print("HI!, Welcome , Iam WeatherBot please ask anything related to weather..")
while True:
try:
goal = read_user_goal()
if not goal:
continue

result = weather_agent.solve(goal)
print_result(result)

except KeyboardInterrupt:
print("\n🤖 Bye!")
break
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix grammatical issues in welcome message.

The welcome message has typographical errors that affect user experience.

📝 Suggested fix
 def main():
     # Step 4: Use your custom agent
-    print("HI!, Welcome , Iam WeatherBot please ask anything related to weather..")
+    print("Hi! Welcome, I am WeatherBot. Please ask anything related to weather.")
     while True:
🤖 Prompt for AI Agents
In `@examples/weather_bot/app/cli_bot.py` around lines 38 - 52, The welcome print
in main() contains grammatical and typographical errors; update the string
passed to print() (the welcome message in main) to a clear, grammatically
correct greeting such as a single sentence that capitalizes properly, removes
extra commas, and introduces the bot (e.g., "Hi! Welcome — I am WeatherBot. Ask
me anything about the weather."). Ensure you edit the print call inside main()
that currently prints the malformed welcome message.

Comment on lines +117 to +120
def load(self, tool: FunctionTool) -> FunctionTool:
if getattr(tool, 'id', None) not in self._tools:
raise ValueError(f"function tool dont have '{tool}' defenition")
return tool
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typos in error message.

The error message contains spelling errors: "dont have" → "doesn't have" and "defenition" → "definition".

📝 Suggested fix
     def load(self, tool: FunctionTool) -> FunctionTool:
         if getattr(tool, 'id', None) not in self._tools:
-            raise ValueError(f"function tool dont have  '{tool}' defenition")
+            raise ValueError(f"FunctionTool '{tool}' is not registered with this provider")
         return tool
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def load(self, tool: FunctionTool) -> FunctionTool:
if getattr(tool, 'id', None) not in self._tools:
raise ValueError(f"function tool dont have '{tool}' defenition")
return tool
def load(self, tool: FunctionTool) -> FunctionTool:
if getattr(tool, 'id', None) not in self._tools:
raise ValueError(f"FunctionTool '{tool}' is not registered with this provider")
return tool
🧰 Tools
🪛 Ruff (0.14.11)

119-119: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
In `@examples/weather_bot/app/tools_base.py` around lines 117 - 120, The
ValueError message in load (FunctionTool) has typos; update the raise to use
correct wording and punctuation (e.g., "function tool doesn't have '{tool}'
definition" or similar) so the message reads clearly; change the string in the
raise inside load that checks getattr(tool, 'id', None) not in self._tools to
the corrected text.

Comment on lines +81 to +83
python -m app.cli_bot
```

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove leading whitespace from command.

The indentation before python -m app.cli_bot may cause rendering issues in some markdown viewers.

-        python -m app.cli_bot
+python -m app.cli_bot
🤖 Prompt for AI Agents
In `@examples/weather_bot/README.md` around lines 81 - 83, Remove the leading
indentation before the command inside the README's fenced code block so the line
reads exactly `python -m app.cli_bot` (no leading spaces) to avoid markdown
rendering issues; update the code block content where the command appears to
ensure the backticks remain on their own lines and the command line has no
preceding whitespace.

Comment on lines +93 to +94
fastapi run app/bot.py
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove leading whitespace from command.

Same issue as above—leading whitespace before the command.

-        fastapi run app/bot.py 
+fastapi run app/bot.py
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fastapi run app/bot.py
```
fastapi run app/bot.py
🤖 Prompt for AI Agents
In `@examples/weather_bot/README.md` around lines 93 - 94, The README contains a
code block line with a leading space before the command "fastapi run
app/bot.py"; remove the leading whitespace so the command starts at column 0
(i.e., change "        fastapi run app/bot.py" to "fastapi run app/bot.py") to
ensure correct rendering and copy-paste behavior in the examples/weather_bot
README.

```


![alt text](screenshorts/image.png) No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Same typo in image path.

This image reference also uses "screenshorts" instead of "screenshots".

-![alt text](screenshorts/image.png)
+![Weather Bot Interface](screenshots/image.png)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
![alt text](screenshorts/image.png)
![Weather Bot Interface](screenshots/image.png)
🤖 Prompt for AI Agents
In `@examples/weather_bot/README.md` at line 124, The image reference in the
README uses the misspelled directory "screenshorts" instead of "screenshots";
update the image path in the Markdown (the line containing "![alt
text](screenshorts/image.png)") to "![alt text](screenshots/image.png)" and
verify the file exists at that corrected path, also search the README for any
other occurrences of "screenshorts" and correct them to "screenshots".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

screenshorts -> screenshots

@rishikesh-jentic
Copy link
Collaborator

@muscodev Apologies for the very late review of the PR. I understand this was probably submitted as a Hacktoberfest submission but it took me a while to get back to PRs on the repo.

The PR looks almost good to be merged. There are some minor comments from CodeRabbit which I think are valid (I have resolved minor nit picks from the tool).

@muscodev
Copy link
Contributor Author

Can we merge it or , any updates are pending?

@rishikesh-jentic
Copy link
Collaborator

@muscodev I see that there are some minor comments from myself and CodeRabbit that are yet to be resolved. I believe once they are resolved we should be good to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants