Skip to content

feat: User can submit a query and receive a response#13

Open
programmer-ke wants to merge 6 commits into
masterfrom
dev
Open

feat: User can submit a query and receive a response#13
programmer-ke wants to merge 6 commits into
masterfrom
dev

Conversation

@programmer-ke

@programmer-ke programmer-ke commented Jul 2, 2026

Copy link
Copy Markdown
Owner

This enable the user get an answer from the agent curated with results from the document index.

Added a find_answer use case that assembles the system prompt, user query and search tool and uses them
to get a response from the agent.

Summary by CodeRabbit

  • New Features

    • The CLI can now generate documentation answers with cited references instead of only showing raw search results.
    • Added notebook examples for agent-based docs search and an OpenAI-powered agent workflow.
  • Bug Fixes

    • Improved query validation and error handling for invalid searches and missing configuration.
    • Added safer handling for agent failures, returning a clear fallback response.
  • Documentation

    • Expanded architecture notes and reorganized the project task list for clearer status tracking.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR replaces direct Whoosh index search with an agent-based question-answering flow. It adds a QueryResponse domain type, agent/tool adapters (OpenAI-backed and fake), a find_answer use case replacing search_index, updated CLI query handling, new demo notebooks, a Makefile black_check target, dependency and docs updates, and a reorganized todo.md.

Changes

Agent Query Answering Feature

Layer / File(s) Summary
QueryResponse domain type
src/docs_buddy/domain/__init__.py
Adds QueryResponse dataclass with JSON __str__/__repr__/fromstring, and updates QueryResult docstring.
Agent/tool adapters
src/docs_buddy/adapters/agent.py, src/docs_buddy/adapters/__init__.py
Adds AgentError/ToolError, make_search_tool, make_fake_research_agent, generate_final_response tool, make_openai_research_agent, run_agent; re-exported from adapters package.
find_answer use case
src/docs_buddy/services/use_cases.py
Removes search_index, adds Agent type alias and find_answer with error handling and logging.
CLI query flow
src/docs_buddy/entrypoints/cli/__main__.py
Rewires --query path to validate query/index, build search tool and prompt, call find_answer, and print answer with citation references.
Tests
tests/integration/test_adapters.py, tests/unit/test_tools.py, tests/unit/test_services.py
Adds tests for search tool creation and reformats/extends service tests, removing the obsolete search_index test.
Dependencies, build, docs, notebooks
pyproject.toml, Makefile, docs/design.md, notebooks/*.org
Adds openai-agents dependency, black_check Makefile target, docs clarifications, and demo notebooks for the agent SDK.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as CLI (__main__.py)
  participant UseCase as find_answer
  participant Agent as research agent
  participant Tool as search tool
  participant Index as DocumentIndex

  User->>CLI: run --query "..."
  CLI->>CLI: validate query & index
  CLI->>Tool: make_search_tool(index)
  CLI->>Agent: make_openai_research_agent(prompt)
  CLI->>UseCase: find_answer(query, agent, [tool])
  UseCase->>Agent: research_query(query, tools)
  Agent->>Tool: search(phrase)
  Tool->>Index: index.search(query)
  Index-->>Tool: results
  Tool-->>Agent: stringified results
  Agent-->>UseCase: QueryResponse
  UseCase-->>CLI: QueryResponse
  CLI-->>User: print answer + citations
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main user-facing change: submitting a query and getting an agent-generated response.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (5)
todo.md (3)

50-80: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mark US-005 as done.

All three scenarios here are checked off, and the new agent-based answer flow is part of this PR. Keeping the story in in progress no longer matches the implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@todo.md` around lines 50 - 80, The US-005 story is still marked as in
progress even though all scenarios are complete and the agent-based answer flow
is implemented. Update the status in todo.md by changing the US-005 checkbox
from in progress to done, keeping the existing scenario checklist intact. Use
the US-005 section header and its current status marker to locate the entry.

25-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move US-007 out of todo.

The CLI query flow and structured response are already implemented in this PR, so leaving this story open makes the tracker stale. Move it to done unless there are still open acceptance criteria.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@todo.md` around lines 25 - 35, Move the US-007 story out of todo.md into the
done tracker because the CLI query flow is already implemented. Update the
checklist entry for US-007 and its scenarios so the status reflects completion,
and verify there are no remaining open acceptance criteria tied to the CLI query
response or error handling before marking it done.

124-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the parked status explicit.

US-001 is marked complete even though both scenarios are still unchecked. That reads as “done” and “not done” at the same time; either leave it open or move it to a dedicated parked state without a checked parent item.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@todo.md` around lines 124 - 135, The parked item status is inconsistent
because US-001 is marked complete while its scenarios remain unchecked. Update
the TODO entry around US-001 so the parent item is not checked, or move it into
a clearly labeled parked state without a completed checkbox, and keep the
scenario checkboxes as-is to reflect the true status.
src/docs_buddy/adapters/__init__.py (1)

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid wildcard import flagged by Ruff (F403).

from .agent import * re-exports everything defined/imported in agent.py (including os, json, asyncio, openai, agents), and Ruff can't verify what's actually used downstream.

♻️ Proposed fix
-from .agent import *
+from .agent import (
+    AgentError,
+    ToolError,
+    make_search_tool,
+    make_fake_research_agent,
+    make_openai_research_agent,
+    run_agent,
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/docs_buddy/adapters/__init__.py` at line 19, Remove the wildcard
re-export in __init__.py that imports everything from the agent module, since
Ruff flags it and it leaks unrelated symbols. Update the package export surface
in src/docs_buddy/adapters/__init__.py by replacing from .agent import * with
explicit imports or a controlled __all__ based on the public API in agent.py, so
only the intended adapter symbols are exposed.

Source: Linters/SAST tools

notebooks/docs_searching_agent.org (1)

69-93: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Notebook's QueryResponse/field naming diverges from the finalized domain type.

The local QueryResponse here uses final_answer, while the shipped domain.QueryResponse uses answer (see src/docs_buddy/domain/__init__.py). Since this notebook demonstrates the same flow now implemented in adapters/agent.py, aligning field names would help readers map the demo to the real API.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@notebooks/docs_searching_agent.org` around lines 69 - 93, Align the
notebook’s response shape with the real domain model by renaming the local
QueryResponse field final_answer to answer and updating generate_final_answer to
construct it with the same field name; keep the dataclass, __str__, and
function_tool example in sync with the shipped domain.QueryResponse and the
adapter flow so readers see the same API surface as in adapters/agent.py.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design.md`:
- Line 5: The phrasing in the design description should use the standard
hyphenated term “domain-driven design” instead of “domain driven design.” Update
the wording in the affected prose so the description remains the same but
follows the correct compound modifier convention.

In `@src/docs_buddy/adapters/agent.py`:
- Around line 118-158: `openai_agent` only catches `json.JSONDecodeError`, so
malformed or unexpected agent output and `run_agent` failures can escape as
non-DocsBuddyError exceptions. Widen the exception handling around both
`asyncio.run(run_agent(...))` and `domain.QueryResponse.fromstring(output)` to
translate any parse/type/network/runtime failure into `AgentError`, keeping the
fallback path in `find_answer` intact. Use the existing `openai_agent` and
`AgentError` symbols to locate the change.
- Around line 72-93: The generate_final_response tool currently returns a
QueryResponse object, but openai_agent expects a JSON/string payload and later
passes result.final_output into QueryResponse.fromstring(...). Update
generate_final_response to return the string form of domain.QueryResponse (or
adjust the downstream parsing to consume the object directly) while keeping the
existing error handling in place. Use the generate_final_response function and
domain.QueryResponse as the key points to locate the fix.

In `@src/docs_buddy/entrypoints/cli/__main__.py`:
- Around line 91-108: The CLI flow in the main entrypoint creates the research
agent without handling `AgentError`, so missing OpenAI configuration currently
crashes with an unhandled traceback. Wrap the
`adapters.make_openai_research_agent(system_prompt)` call in the same style as
the nearby `domain.InvalidQueryError` and missing-index handling, catch
`AgentError`, log a clear CLI error, and exit nonzero; keep the fix localized to
the entrypoint logic that builds `research_user_query` before calling
`services.find_answer`.

---

Nitpick comments:
In `@notebooks/docs_searching_agent.org`:
- Around line 69-93: Align the notebook’s response shape with the real domain
model by renaming the local QueryResponse field final_answer to answer and
updating generate_final_answer to construct it with the same field name; keep
the dataclass, __str__, and function_tool example in sync with the shipped
domain.QueryResponse and the adapter flow so readers see the same API surface as
in adapters/agent.py.

In `@src/docs_buddy/adapters/__init__.py`:
- Line 19: Remove the wildcard re-export in __init__.py that imports everything
from the agent module, since Ruff flags it and it leaks unrelated symbols.
Update the package export surface in src/docs_buddy/adapters/__init__.py by
replacing from .agent import * with explicit imports or a controlled __all__
based on the public API in agent.py, so only the intended adapter symbols are
exposed.

In `@todo.md`:
- Around line 50-80: The US-005 story is still marked as in progress even though
all scenarios are complete and the agent-based answer flow is implemented.
Update the status in todo.md by changing the US-005 checkbox from in progress to
done, keeping the existing scenario checklist intact. Use the US-005 section
header and its current status marker to locate the entry.
- Around line 25-35: Move the US-007 story out of todo.md into the done tracker
because the CLI query flow is already implemented. Update the checklist entry
for US-007 and its scenarios so the status reflects completion, and verify there
are no remaining open acceptance criteria tied to the CLI query response or
error handling before marking it done.
- Around line 124-135: The parked item status is inconsistent because US-001 is
marked complete while its scenarios remain unchecked. Update the TODO entry
around US-001 so the parent item is not checked, or move it into a clearly
labeled parked state without a completed checkbox, and keep the scenario
checkboxes as-is to reflect the true status.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b27c1f0a-5231-43de-8d35-6f97768483ff

📥 Commits

Reviewing files that changed from the base of the PR and between b27fb68 and cecc3e1.

📒 Files selected for processing (14)
  • Makefile
  • docs/design.md
  • notebooks/docs_searching_agent.org
  • notebooks/openai_agent_sdk_intro.org
  • pyproject.toml
  • src/docs_buddy/adapters/__init__.py
  • src/docs_buddy/adapters/agent.py
  • src/docs_buddy/domain/__init__.py
  • src/docs_buddy/entrypoints/cli/__main__.py
  • src/docs_buddy/services/use_cases.py
  • tests/integration/test_adapters.py
  • tests/unit/test_services.py
  • tests/unit/test_tools.py
  • todo.md

Comment thread docs/design.md

## Repository Structure

It matches the domain driven design architecture of the application

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Hyphenate "domain-driven design."

✏️ Proposed fix
-It matches the domain driven design architecture of the application
+It matches the domain-driven design architecture of the application
📝 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
It matches the domain driven design architecture of the application
It matches the domain-driven design architecture of the application
🧰 Tools
🪛 LanguageTool

[grammar] ~5-~5: Use a hyphen to join words.
Context: ...ository Structure It matches the domain driven design architecture of the applic...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design.md` at line 5, The phrasing in the design description should use
the standard hyphenated term “domain-driven design” instead of “domain driven
design.” Update the wording in the affected prose so the description remains the
same but follows the correct compound modifier convention.

Source: Linters/SAST tools

Comment on lines +72 to +93
@agents.function_tool
def generate_final_response(
final_answer: str, citations: list[str]
) -> domain.QueryResponse:
"""Generates the final response to the user's query in a structed format

Args:
final_answer (str): The final answer to the user's query
citations (list[str]): A list of paths from the search tool results that were instrumental
in generating the answer

Returns:
QueryResponse: A structured response to the user's query
"""

try:
final_response = domain.QueryResponse(final_answer, citations)
except (TypeError, ValueError) as exc:
raise AgentError("Could not create response") from exc

return final_response

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does openai-agents-python version 0.17.7 stringify a dataclass return value from a StopAtTools tool via str() before setting final_output?

💡 Result:

In openai-agents-python version 0.17.7, StopAtTools does not automatically stringify a dataclass return value via str before setting it as the final output. When StopAtTools is configured to stop on a specific tool, the tool's return value is used directly as the final output [1][2]. If a tool returns a dataclass, that dataclass object is passed through as the final output, preserving its type [3]. Users are then able to access this output in a structured format, for example, by using result.final_output_as(MyDataclassType) after running the agent [3]. There is no logic within the StopAtTools handling mechanism that coerces these return values to strings [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant adapter and response types, then print the surrounding lines.
git ls-files | rg '(^|/)src/docs_buddy/adapters/agent\.py$|(^|/)src/docs_buddy/.+\.py$|(^|/)pyproject\.toml$'
printf '\n--- agent.py ---\n'
cat -n src/docs_buddy/adapters/agent.py | sed -n '1,240p'

printf '\n--- query response references ---\n'
rg -n "class QueryResponse|fromstring\(|final_output|StopAtTools|generate_final_response|openai_agent" src/docs_buddy -n

Repository: programmer-ke/docs-buddy

Length of output: 8509


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the QueryResponse implementation and agent output handling.
cat -n src/docs_buddy/domain.py | sed -n '1,240p'
printf '\n--- openai_agent references ---\n'
rg -n "fromstring\(|QueryResponse\(|final_output|StopAtTools|result\.final_output" src/docs_buddy -n

Repository: programmer-ke/docs-buddy

Length of output: 219


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n--- pyproject version pin ---\n'
rg -n 'openai-agents|agents==' pyproject.toml

printf '\n--- domain/__init__.py around QueryResponse ---\n'
cat -n src/docs_buddy/domain/__init__.py | sed -n '80,140p'

Repository: programmer-ke/docs-buddy

Length of output: 2034


Return a JSON string from generate_final_response
StopAtTools passes the tool return value through as result.final_output, so openai_agent is handing a QueryResponse object to QueryResponse.fromstring(...). Return str(domain.QueryResponse(...)) here, or parse result.final_output as a QueryResponse directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/docs_buddy/adapters/agent.py` around lines 72 - 93, The
generate_final_response tool currently returns a QueryResponse object, but
openai_agent expects a JSON/string payload and later passes result.final_output
into QueryResponse.fromstring(...). Update generate_final_response to return the
string form of domain.QueryResponse (or adjust the downstream parsing to consume
the object directly) while keeping the existing error handling in place. Use the
generate_final_response function and domain.QueryResponse as the key points to
locate the fix.

Comment on lines +118 to +158
def openai_agent(
query: domain.Query, tools: list[Callable]
) -> domain.QueryResponse:
"""OpenaAI compatible agent that answers user's query"""

final_response_callout = (
"IMPORTANT: Always call generate_final_response as your final output."
)

system_instructions = f"""\
{prompt}

{final_response_callout}
"""

agent = agents.Agent(
name="Docs Buddy Agent",
instructions=textwrap.dedent(system_instructions),
tools=[agents.function_tool(func) for func in tools] # type: ignore[arg-type]
+ [generate_final_response],
tool_use_behavior=agents.agent.StopAtTools(
stop_at_tool_names=["generate_final_response"]
),
)

result = asyncio.run(
run_agent(
agent,
str(query),
agents.RunConfig(model_provider=CUSTOM_MODEL_PROVIDER),
)
)

output: str = result.final_output
try:
response = domain.QueryResponse.fromstring(output)
except json.JSONDecodeError as exc:
raise AgentError("Could not parse query response from llm") from exc
return response

return openai_agent

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Incomplete exception handling lets malformed agent output crash the caller instead of falling back gracefully.

except json.JSONDecodeError only covers decode failures. If output is valid JSON but doesn't exactly match QueryResponse's fields (extra/missing keys), domain.QueryResponse.fromstring raises TypeError, which is not a DocsBuddyError and will propagate straight through openai_agent, then through find_answer's except DocsBuddyError handler (services/use_cases.py lines 186-200) unhandled — defeating the intended "Something went wrong, please try again" fallback and crashing the CLI/caller instead.

The same applies to any other unexpected exception from asyncio.run(run_agent(...)) (e.g. network/timeout/API errors from the openai client), none of which are DocsBuddyError subtypes.

🛡️ Proposed fix to widen error translation
         output: str = result.final_output
         try:
             response = domain.QueryResponse.fromstring(output)
-        except json.JSONDecodeError as exc:
+        except (json.JSONDecodeError, TypeError) as exc:
             raise AgentError("Could not parse query response from llm") from exc
         return response

Consider also wrapping the asyncio.run(run_agent(...)) call so unexpected client/network errors are translated into AgentError before reaching find_answer.

📝 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 openai_agent(
query: domain.Query, tools: list[Callable]
) -> domain.QueryResponse:
"""OpenaAI compatible agent that answers user's query"""
final_response_callout = (
"IMPORTANT: Always call generate_final_response as your final output."
)
system_instructions = f"""\
{prompt}
{final_response_callout}
"""
agent = agents.Agent(
name="Docs Buddy Agent",
instructions=textwrap.dedent(system_instructions),
tools=[agents.function_tool(func) for func in tools] # type: ignore[arg-type]
+ [generate_final_response],
tool_use_behavior=agents.agent.StopAtTools(
stop_at_tool_names=["generate_final_response"]
),
)
result = asyncio.run(
run_agent(
agent,
str(query),
agents.RunConfig(model_provider=CUSTOM_MODEL_PROVIDER),
)
)
output: str = result.final_output
try:
response = domain.QueryResponse.fromstring(output)
except json.JSONDecodeError as exc:
raise AgentError("Could not parse query response from llm") from exc
return response
return openai_agent
def openai_agent(
query: domain.Query, tools: list[Callable]
) -> domain.QueryResponse:
"""OpenaAI compatible agent that answers user's query"""
final_response_callout = (
"IMPORTANT: Always call generate_final_response as your final output."
)
system_instructions = f"""\
{prompt}
{final_response_callout}
"""
agent = agents.Agent(
name="Docs Buddy Agent",
instructions=textwrap.dedent(system_instructions),
tools=[agents.function_tool(func) for func in tools] # type: ignore[arg-type]
[generate_final_response],
tool_use_behavior=agents.agent.StopAtTools(
stop_at_tool_names=["generate_final_response"]
),
)
result = asyncio.run(
run_agent(
agent,
str(query),
agents.RunConfig(model_provider=CUSTOM_MODEL_PROVIDER),
)
)
output: str = result.final_output
try:
response = domain.QueryResponse.fromstring(output)
except (json.JSONDecodeError, TypeError) as exc:
raise AgentError("Could not parse query response from llm") from exc
return response
return openai_agent
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/docs_buddy/adapters/agent.py` around lines 118 - 158, `openai_agent` only
catches `json.JSONDecodeError`, so malformed or unexpected agent output and
`run_agent` failures can escape as non-DocsBuddyError exceptions. Widen the
exception handling around both `asyncio.run(run_agent(...))` and
`domain.QueryResponse.fromstring(output)` to translate any
parse/type/network/runtime failure into `AgentError`, keeping the fallback path
in `find_answer` intact. Use the existing `openai_agent` and `AgentError`
symbols to locate the change.

Comment on lines +91 to +108
try:
query = domain.Query(args.query)
except domain.InvalidQueryError as exc:
log.error("Invalid query detected: %s", exc)
sys.exit(1)

base_url = f"https://github.com/{repo_id}/blob/main/"

tools = [adapters.make_search_tool(document_index)]

system_prompt = textwrap.dedent("""\
You are a documentation assistant equipped to answer user queries
by searching the docs.
""")

research_user_query = adapters.make_openai_research_agent(system_prompt)

response = services.find_answer(query, research_user_query, tools)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Unhandled AgentError when OpenAI credentials aren't configured.

adapters.make_openai_research_agent(system_prompt) raises AgentError if OPENAI_BASE_URL/OPENAI_API_KEY/DOCS_BUDDY_MODEL_NAME are missing. Unlike the invalid-query and missing-index cases just above it in this same function, this call isn't wrapped in a try/except, so it will surface as an unhandled traceback rather than a clean CLI error.

🛡️ Proposed fix
-        research_user_query = adapters.make_openai_research_agent(system_prompt)
+        try:
+            research_user_query = adapters.make_openai_research_agent(system_prompt)
+        except adapters.AgentError as exc:
+            log.error("Agent configuration error: %s", exc)
+            sys.exit(1)
📝 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
try:
query = domain.Query(args.query)
except domain.InvalidQueryError as exc:
log.error("Invalid query detected: %s", exc)
sys.exit(1)
base_url = f"https://github.com/{repo_id}/blob/main/"
tools = [adapters.make_search_tool(document_index)]
system_prompt = textwrap.dedent("""\
You are a documentation assistant equipped to answer user queries
by searching the docs.
""")
research_user_query = adapters.make_openai_research_agent(system_prompt)
response = services.find_answer(query, research_user_query, tools)
try:
query = domain.Query(args.query)
except domain.InvalidQueryError as exc:
log.error("Invalid query detected: %s", exc)
sys.exit(1)
base_url = f"https://github.com/{repo_id}/blob/main/"
tools = [adapters.make_search_tool(document_index)]
system_prompt = textwrap.dedent("""\
You are a documentation assistant equipped to answer user queries
by searching the docs.
""")
try:
research_user_query = adapters.make_openai_research_agent(system_prompt)
except adapters.AgentError as exc:
log.error("Agent configuration error: %s", exc)
sys.exit(1)
response = services.find_answer(query, research_user_query, tools)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/docs_buddy/entrypoints/cli/__main__.py` around lines 91 - 108, The CLI
flow in the main entrypoint creates the research agent without handling
`AgentError`, so missing OpenAI configuration currently crashes with an
unhandled traceback. Wrap the
`adapters.make_openai_research_agent(system_prompt)` call in the same style as
the nearby `domain.InvalidQueryError` and missing-index handling, catch
`AgentError`, log a clear CLI error, and exit nonzero; keep the fix localized to
the entrypoint logic that builds `research_user_query` before calling
`services.find_answer`.

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.

1 participant