Skip to content

Conversation

aaronsteers
Copy link
Contributor

@aaronsteers aaronsteers commented Oct 12, 2025

Replace openai-agents with pydantic-ai implementation

Summary

Migrated the connector builder MCP from openai-agents to pydantic-ai, updating the agent architecture, tool delegation mechanisms, and dependencies across both the main package and the connector_builder_agents subpackage.

Key changes:

  • Agent framework: Replaced openai-agents.Agent with pydantic_ai.Agent
  • Delegation pattern: Changed from explicit handoff() classes to tool-based delegation using RunContext
  • Web search: Switched from WebSearchTool() to duckduckgo_search_tool() from pydantic-ai
  • Message tracking: Added message_history to SessionState for pydantic-ai's message management
  • MCP integration: Changed from mcp_servers parameter to toolsets.append() for attaching MCP servers
  • Dependencies: Updated both pyproject.toml files (root and connector_builder_agents/) to use pydantic-ai packages

Review & Testing Checklist for Human

⚠️ Critical - This PR changes the core agent communication architecture. CI passing is necessary but insufficient validation.

  • Test end-to-end connector build workflow - Run actual connector builds to verify manager→developer delegation works correctly
  • Verify evals functionality - Run /build-connector command to confirm evals work with pydantic-ai (initial failure was fixed by adding pydantic-ai to connector_builder_agents/pyproject.toml)
  • Test web search capability - Confirm DuckDuckGo search tool provides adequate results (different implementation than old WebSearchTool)
  • Validate MCP tool access - Verify all MCP tools are accessible to both manager and developer agents
  • Check message history/context - Ensure conversation context properly carries over between agent delegations

Notes

  • CI checks all pass ✅ including Deptry, formatting, linting, and tests
  • Two separate package configurations exist (root + connector_builder_agents/), both updated with pydantic-ai deps
  • Deptry config updated to exclude evals/ subdirectory to prevent false positives
  • Agent behavior in production scenarios needs manual verification beyond unit tests

Link to Devin run: https://app.devin.ai/sessions/0011f26c17d1458b81190e5bcfe5e0f7
Requested by: @aaronsteers

Summary by CodeRabbit

  • New Features

    • Manager→developer delegation via tool-based flow with structured progress reporting.
    • Built-in web search switched to DuckDuckGo.
    • Session history tracking and generated session IDs.
  • Improvements

    • Streamlined interactive runs with clearer progress updates and simplified startup (no auto-init side effects).
    • Default manager/developer models set to GPT‑4o.
    • Manager prompt composition refined.
  • Refactor

    • Unified agent framework and simplified MCP server/tool construction; tool factories streamlined.
  • Chores

    • Updated dependencies to support the new agent stack.

- Migrated from openai-agents to pydantic-ai framework
- Replaced Agent class from agents with Agent from pydantic_ai
- Updated agent creation to use pydantic-ai patterns
- Replaced handoff mechanism with tool-based delegation
- Updated manager agent to delegate to developer using @agent.tool decorator
- Replaced Runner.run with Agent.run methods
- Replaced session-based management with message_history tracking
- Updated MCP server integration to use pydantic_ai.mcp.MCPServerStdio
- Removed function_tool decorators (pydantic-ai tools are plain functions)
- Updated dependencies in pyproject.toml to use pydantic-ai and pydantic-ai-slim
- Preserved manager-developer architecture and 3-phase workflow
- All tests passing (98 passed, 2 skipped, 1 xfailed)

Co-Authored-By: AJ Steers <[email protected]>
Copy link
Contributor

Original prompt from AJ Steers
@Devin - Replace the openai-agents implementation in connector-builder-mcp with a pydantic-ai implementation.
Thread URL: https://airbytehq-team.slack.com/archives/D089P0UPVT4/p1760244354765309?thread_ts=1760244354.765309

Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link

coderabbitai bot commented Oct 12, 2025

📝 Walkthrough

Walkthrough

Replaces OpenAI-specific agents and handoff models with pydantic_ai Agents and tool-based delegation/reporting, standardizes MCP integration to MCPServerStdio, simplifies run/session orchestration with session_state and message_history, changes default models to "openai:gpt-4o", and adds pydantic-ai and emoji dependencies.

Changes

Cohort / File(s) Summary
Agent refactor & delegation
connector_builder_agents/src/agents.py
Swapped OpenAIAgentAgent (pydantic_ai); removed DelegatedDeveloperTask, ManagerHandoffInput, and handoff helpers; added delegate_to_developer (manager-bound) and report_back_to_manager (developer-bound) tools; append MCP servers to agents' toolsets; logging now uses RunContext deps; create_developer_agent/create_manager_agent return Agent.
Constants & config
connector_builder_agents/src/constants.py
Removed dynamic OpenAI/GitHub endpoint initialization and initialize_models(); changed DEFAULT_DEVELOPER_MODEL and DEFAULT_MANAGER_MODEL"openai:gpt-4o"; added AUTO_OPEN_TRACE_URL; retained dotenv loading but removed side-effect model initialization.
Prompts / guidance
connector_builder_agents/src/guidance.py
Removed RECOMMENDED_PROMPT_PREFIX from manager prompt composition; manager prompt uses ROOT_PROMPT_FILE_STR only.
Run orchestration & session
connector_builder_agents/src/run.py
Replaced prior session/backends/tracing with agent-driven flow using Agent.run; removed legacy session types and Runner; added generate_session_id; broadened run return types to `list
MCP & tool factories
connector_builder_agents/src/tools.py
Switched MCP factories to construct MCPServerStdio directly (simplified args); added message_history: list to SessionState; converted many decorator-registered tools into factories that return plain callables; removed detailed MCP tool-filtering params.
Evals task change
connector_builder_agents/src/evals/task.py
run_connector_build_task now reads final output from final_result.output instead of final_result.final_output.
Project deps / packaging
pyproject.toml, connector_builder_agents/pyproject.toml
Added dependencies: emoji>=2.0.0,<3.0, pydantic-ai>=0.0.14,<1.0, pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0; replaced openai-agents/mcp-agent with pydantic-ai variants; updated deptry exclude path.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant Manager as Manager Agent
  participant Dev as Developer Agent
  participant MCP as MCP Servers

  User->>Manager: submit assignment (title, description)
  Manager->>Manager: plan / decide to delegate
  Manager->>Manager: call delegate_to_developer(...)
  Manager->>Dev: invoke developer_agent.run(ctx, task)
  activate Dev
  Dev->>MCP: call MCP tools (filesystem/browser/connector)
  MCP-->>Dev: return tool results
  Dev->>Manager: call report_back_to_manager(status, summary)
  deactivate Dev
  Manager->>Manager: update session_state / message_history
  alt not complete
    Manager->>Dev: delegate_to_developer(...)
  else complete
    Manager-->>User: final outputs/status
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 succinctly and accurately captures the primary change of migrating the agent implementation from openai-agents to pydantic-ai, reflecting the core intent of the PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1760288645-replace-openai-agents-with-pydantic-ai

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

@github-actions github-actions bot added the enhancement New feature or request label Oct 12, 2025
Copy link

👋 Welcome to the Airbyte Connector Builder MCP!

Thank you for your contribution! Here are some helpful tips and reminders for your convenience.

Testing This Branch via MCP

To test the changes in this specific branch with an MCP client like Claude Desktop, use the following configuration:

{
  "mcpServers": {
    "connector-builder-mcp-dev": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/airbytehq/connector-builder-mcp.git@devin/1760288645-replace-openai-agents-with-pydantic-ai", "connector-builder-mcp"]
    }
  }
}

Testing This Branch via CLI

You can test this version of the MCP Server using the following CLI snippet:

# Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/connector-builder-mcp.git@devin/1760288645-replace-openai-agents-with-pydantic-ai#egg=airbyte-connector-builder-mcp' --help

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /autofix - Fixes most formatting and linting issues
  • /build-connector - Builds the default connector on-demand using the AI builder
  • /build-connector prompt="<your prompt>" - Builds a connector on-demand using the AI builder
  • /poe <command> - Runs any poe command in the uv virtual environment

AI Builder Evaluations

AI builder evaluations run automatically under the following conditions:

  • When a PR is marked as "ready for review"
  • When a PR is reopened

A set of standardized evaluations also run on a schedule (Mon/Wed/Fri at midnight UTC) and can be manually triggered via workflow dispatch.

Helpful Resources

If you have any questions, feel free to ask in the PR comments or join our Slack community.

📝 Edit this welcome message.

Copy link

github-actions bot commented Oct 12, 2025

PyTest Results (Full)

0 tests   0 ✅  0s ⏱️
0 suites  0 💤
0 files    0 ❌

Results for commit 7d21084.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Oct 12, 2025

PyTest Results (Fast)

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit 7d21084. ± Comparison against base commit 45b1b8c.

♻️ This comment has been updated with latest results.

- Imported duckduckgo_search from pydantic_ai.tools
- Added to developer agent's tools list
- Replaces the previous WebSearchTool from openai-agents
- Addresses web search capability checklist item from PR description

Co-Authored-By: AJ Steers <[email protected]>
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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pyproject.toml (1)

30-31: Remove duplicated dev dependency.

poethepoet is listed twice. Keep the newer pin only.

-    "poethepoet>=0.29.0",
     "poethepoet>=0.37.0",
🧹 Nitpick comments (9)
pyproject.toml (1)

69-69: Align mypy target python with runtime.

requires-python is ">=3.11" but mypy is set to "3.10". Set to 3.11 to avoid mismatches in type inference.

Suggested:

[tool.mypy]
python_version = "3.11"
connector_builder_agents/src/run.py (4)

28-31: Use a collision‑free session id.

int(time.time()) can collide under concurrency. Prefer UUID.

-def generate_session_id() -> str:
-    """Generate a unique session ID based on current timestamp."""
-    return f"unified-mcp-session-{int(time.time())}"
+import uuid
+
+def generate_session_id() -> str:
+    """Generate a unique session ID."""
+    return f"unified-mcp-session-{uuid.uuid4()}"

98-105: Avoid CWD‑relative prompt path; use the module constant.

This will fail if run outside repo root. Reuse ROOT_PROMPT_FILE_STR.

-        prompt_file = Path("./prompts") / "root-prompt.md"
-        prompt = prompt_file.read_text(encoding="utf-8") + "\n\n"
-        prompt += instructions
+        from .constants import ROOT_PROMPT_FILE_STR
+        prompt = ROOT_PROMPT_FILE_STR + "\n\n" + instructions

200-234: Add safety limits and trim message history to prevent unbounded growth.

  • Loop can run indefinitely if agents never mark completion.
  • message_history grows without bounds.
-        while not is_complete(session_state):
+        from .constants import MAX_CONNECTOR_BUILD_STEPS
+        MAX_HISTORY = 200  # local cap; consider promoting to constants
+        while not is_complete(session_state) and iteration_count < MAX_CONNECTOR_BUILD_STEPS:
@@
-            session_state.message_history.extend(run_result.new_messages())
+            session_state.message_history.extend(run_result.new_messages())
+            if len(session_state.message_history) > MAX_HISTORY:
+                session_state.message_history = session_state.message_history[-MAX_HISTORY:]
@@
-        return all_run_results
+        if not is_complete(session_state):
+            update_progress_log("⏹ Reached max iterations; stopping.", session_state)
+        return all_run_results

236-241: Avoid sys.exit in run_manager_developer_build.

Return cleanly so callers control process termination.

-    except KeyboardInterrupt:
+    except KeyboardInterrupt:
         update_progress_log("\n🛑 Build terminated (ctrl+c input received).", session_state)
-        sys.exit(0)
+        return all_run_results if 'all_run_results' in locals() else []
connector_builder_agents/src/agents.py (2)

106-121: Handle errors from delegated developer runs.

If the developer toolchain fails (tool error/timeout), log via log_tool_failure and propagate a concise message to the manager to decide next steps.

-        result = await developer_agent.run(
+        try:
+            result = await developer_agent.run(
                 assignment_description,
                 message_history=ctx.deps.message_history,
                 deps=ctx.deps,
             )
+        except Exception as e:
+            update_progress_log(
+                f"🛠️ Delegation failed for '{assignment_title}': {e}", ctx.deps
+            )
+            return f"Delegation failed: {e}"

118-120: Cap shared message history to avoid ballooning.

Same concern as in run.py; trim after extending.

-        ctx.deps.message_history.extend(result.new_messages())
+        ctx.deps.message_history.extend(result.new_messages())
+        if len(ctx.deps.message_history) > 200:
+            ctx.deps.message_history = ctx.deps.message_history[-200:]
connector_builder_agents/src/tools.py (2)

22-31: Avoid mutable default for message_history.

Use Field(default_factory=list) and drop manual kwargs handling.

-    message_history: list = []
+    message_history: list = Field(default_factory=list)
@@
-        message_history = kwargs.get("message_history", [])
@@
         super().__init__(
             workspace_dir=workspace_dir,
             execution_log_file=execution_log_file,
-            message_history=message_history,
+            # Let Pydantic default_factory create a fresh list per instance
             start_time=start_time,
             **kwargs,
         )

Also applies to: 40-44


58-73: Duplicate connector‑builder MCP servers; reuse a single instance.

Two identical MCPServerStdio("uv", ["run","airbyte-connector-builder-mcp"]) are spawned, contradicting the “reuse instances” docstring and wasting resources.

-connector_builder_dev = MCP_CONNECTOR_BUILDER_FOR_DEVELOPER()
-connector_builder_manager = MCP_CONNECTOR_BUILDER_FOR_MANAGER()
+connector_builder = MCP_CONNECTOR_BUILDER_FOR_DEVELOPER()
@@
-    all_servers = [
+    all_servers = [
         # MCP_PLAYWRIGHT_WEB_BROWSER(),
-        connector_builder_dev,
-        connector_builder_manager,
+        connector_builder,
         filesystem_server,
     ]
@@
-    manager_servers = [
-        connector_builder_manager,
+    manager_servers = [
+        connector_builder,
         filesystem_server,
     ]
@@
-    developer_servers = [
+    developer_servers = [
         # MCP_PLAYWRIGHT_WEB_BROWSER(),
-        connector_builder_dev,
+        connector_builder,
         filesystem_server,
     ]

Or drop the separate lambdas and define a single MCP_CONNECTOR_BUILDER factory.

Also applies to: 106-127

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45b1b8c and d9731ed.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • connector_builder_agents/src/agents.py (3 hunks)
  • connector_builder_agents/src/constants.py (1 hunks)
  • connector_builder_agents/src/guidance.py (0 hunks)
  • connector_builder_agents/src/run.py (5 hunks)
  • connector_builder_agents/src/tools.py (5 hunks)
  • pyproject.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • connector_builder_agents/src/guidance.py
🧰 Additional context used
🧬 Code graph analysis (2)
connector_builder_agents/src/run.py (3)
connector_builder_agents/src/_util.py (1)
  • get_secrets_dotenv (29-88)
connector_builder_agents/src/agents.py (2)
  • create_developer_agent (23-51)
  • create_manager_agent (54-151)
connector_builder_agents/src/tools.py (4)
  • SessionState (17-50)
  • update_progress_log (144-168)
  • is_complete (48-50)
  • is_complete (132-134)
connector_builder_agents/src/agents.py (2)
connector_builder_agents/src/tools.py (5)
  • SessionState (17-50)
  • create_log_progress_milestone_from_developer_tool (284-291)
  • create_log_problem_encountered_by_developer_tool (264-271)
  • create_log_tool_failure_tool (220-251)
  • update_progress_log (144-168)
connector_builder_agents/src/guidance.py (2)
  • get_default_developer_prompt (76-93)
  • get_default_manager_prompt (58-73)
🪛 GitHub Actions: Dependency Analysis
pyproject.toml

[error] 1-1: DEP002 'pydantic-ai' defined as a dependency but not used in the codebase.


[error] 1-1: DEP002 'pydantic-ai-slim' defined as a dependency but not used in the codebase.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Pytest (Fast)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
🔇 Additional comments (2)
connector_builder_agents/src/agents.py (1)

4-6: Verify availability of duckduckgo_search tool.

Ensure duckduckgo_search works without extra install. If it requires an extra, add it to project deps or the new agents extra.

If needed, add:

[project.optional-dependencies]
agents = [
  "pydantic-ai[duckduckgo]",
  # or the specific package providing duckduckgo search
]
connector_builder_agents/src/constants.py (1)

16-18: Clarify model ID format for pydantic-ai

Agent shorthand supports provider-prefixed IDs (e.g. Agent("openai:gpt-4o")), but direct OpenAI model instantiation (e.g. OpenAIChatModel) expects the raw name ("gpt-4o"). Ensure DEFAULT_DEVELOPER_MODEL and DEFAULT_MANAGER_MODEL are only used with Agent; otherwise strip the openai: prefix.

Comment on lines 133 to 156
update_progress_log("\n⚙️ AI Agent is working...", session_state)
try:
result = await agent.run(
input_prompt,
message_history=session_state.message_history,
deps=session_state,
)

session_state.message_history.extend(result.new_messages())

update_progress_log(f"\n🤖 AI Agent: {result.data}", session_state)

input_prompt = input("\n👤 You: ")
if input_prompt.lower() in {"exit", "quit"}:
update_progress_log("☑️ Ending conversation...", session_state)
break

except KeyboardInterrupt:
update_progress_log(
"\n🛑 Conversation terminated (ctrl+c input received).", session_state
)
sys.exit(0)

return None
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

Don’t block the event loop or exit the process in a library function.

  • input() blocks in an async function.
  • sys.exit(0) will terminate the whole process; prefer returning gracefully.
-            input_prompt = input("\n👤  You: ")
+            # Non-blocking input in async context
+            import asyncio
+            loop = asyncio.get_event_loop()
+            input_prompt = await loop.run_in_executor(None, input, "\n👤  You: ")
             if input_prompt.lower() in {"exit", "quit"}:
                 update_progress_log("☑️ Ending conversation...", session_state)
                 break
-        except KeyboardInterrupt:
+        except KeyboardInterrupt:
             update_progress_log(
                 "\n🛑 Conversation terminated (ctrl+c input received).", session_state
             )
-            sys.exit(0)
+            return None
📝 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
update_progress_log("\n⚙️ AI Agent is working...", session_state)
try:
result = await agent.run(
input_prompt,
message_history=session_state.message_history,
deps=session_state,
)
session_state.message_history.extend(result.new_messages())
update_progress_log(f"\n🤖 AI Agent: {result.data}", session_state)
input_prompt = input("\n👤 You: ")
if input_prompt.lower() in {"exit", "quit"}:
update_progress_log("☑️ Ending conversation...", session_state)
break
except KeyboardInterrupt:
update_progress_log(
"\n🛑 Conversation terminated (ctrl+c input received).", session_state
)
sys.exit(0)
return None
update_progress_log("\n⚙️ AI Agent is working...", session_state)
try:
result = await agent.run(
input_prompt,
message_history=session_state.message_history,
deps=session_state,
)
session_state.message_history.extend(result.new_messages())
update_progress_log(f"\n🤖 AI Agent: {result.data}", session_state)
# Non-blocking input in async context
import asyncio
loop = asyncio.get_event_loop()
input_prompt = await loop.run_in_executor(None, input, "\n👤 You: ")
if input_prompt.lower() in {"exit", "quit"}:
update_progress_log("☑️ Ending conversation...", session_state)
break
except KeyboardInterrupt:
update_progress_log(
"\n🛑 Conversation terminated (ctrl+c input received).", session_state
)
return None
return None
🤖 Prompt for AI Agents
In connector_builder_agents/src/run.py around lines 133 to 156, the code uses
blocking input() inside an async function and calls sys.exit(0) in the
KeyboardInterrupt handler; replace blocking input() with an async-friendly
approach (either accept an injected async input callback from caller, or wrap
input() with asyncio.to_thread to avoid blocking the event loop) and remove
sys.exit(0) so the function returns gracefully on KeyboardInterrupt (return None
or raise a controlled exception up to caller). Also ensure update_progress_log
is called before returning so the caller can continue/cleanup.

Comment on lines +64 to 65
env={},
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Confirm env={} semantics on MCPServerStdio.

If env replaces rather than merges with os.environ, this can strip needed variables (e.g., credentials). Prefer omitting env or explicitly merging.

If replace: construct via:

import os
MCPServerStdio(cmd, args, env=os.environ.copy() | extra_env)

Also applies to: 72-73, 81-82, 93-94


🌐 Web query:

In pydantic-ai MCPServerStdio, does passing env={} replace the entire environment or merge with the current environment?

💡 Result:

Passing env={} replaces the subprocess environment with exactly the mapping you provide (so an empty env yields no inherited vars). To inherit the parent env, pass env=os.environ. [1]


Preserve inherited environment in all MCPServerStdio invocations
Passing env={} replaces the subprocess environment and strips inherited variables. At lines 64-65, 72-73, 81-82, and 93-94, either omit the env argument or explicitly merge with the parent environment (e.g. env=os.environ.copy() | extra_env).

🤖 Prompt for AI Agents
In connector_builder_agents/src/tools.py around lines 64-65 (also addressing
similar calls at 72-73, 81-82 and 93-94), the MCPServerStdio invocations pass
env={} which replaces the subprocess environment and strips inherited variables;
instead preserve the parent environment by omitting the env argument or merging
with os.environ (e.g., create a copy of os.environ and update it with any extra
env values) so subprocesses inherit existing variables, then pass that merged
dict as the env parameter.

pyproject.toml Outdated
Comment on lines 16 to 17
"pydantic-ai>=0.0.14,<1.0",
"pydantic-ai-slim[openai]>=0.0.14,<1.0",
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Fix deptry failures: move pydantic‑ai deps to an optional extra or include agents package in the wheel.

Deptry flags these as unused because connector_builder_agents/ is excluded from analysis and not in wheel packages. Choose one:

  • Preferred: move to an optional extra (e.g., agents) and keep [tool.deptry] as‑is.
  • Or: include connector_builder_agents in [tool.hatch.build.targets.wheel].packages and remove it from deptry’s exclude.

Apply this diff to remove the direct deps now:

-    "pydantic-ai>=0.0.14,<1.0",
-    "pydantic-ai-slim[openai]>=0.0.14,<1.0",

Then add this section (outside the changed lines) to declare the extra:

[project.optional-dependencies]
agents = [
  "pydantic-ai>=0.0.14,<1.0",
  "pydantic-ai-slim[openai]>=0.0.14,<1.0",
]

Alternatively, include the package and un‑exclude it:

# In [tool.hatch.build.targets.wheel]
packages = ["connector_builder_mcp", "connector_builder_agents"]

# In [tool.deptry]
exclude = [
  ".venv/",
  "tests/",
]

Run deptry locally after either change to confirm the error is gone.


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
echo "1. Checking for connector_builder_agents directory..."
fd --type d connector_builder_agents .

echo ""
echo "2. Inspecting wheel build targets in pyproject.toml..."
rg -n 'tool.hatch.build.targets.wheel' -A5 -B2 pyproject.toml

echo ""
echo "3. Inspecting deptry exclude configuration in pyproject.toml..."
rg -n 'tool.deptry' -A5 -B2 pyproject.toml

Length of output: 506


Move pydantic-ai deps into an optional agents extra or include connector_builder_agents in the wheel build.

  • Preferred: in pyproject.toml, remove
    "pydantic-ai>=0.0.14,<1.0",
    "pydantic-ai-slim[openai]>=0.0.14,<1.0",
    from the base [project] deps and add under
    [project.optional-dependencies]
    agents = [
      "pydantic-ai>=0.0.14,<1.0",
      "pydantic-ai-slim[openai]>=0.0.14,<1.0",
    ]
  • Alternatively: in
    [tool.hatch.build.targets.wheel].packages add "connector_builder_agents",
    and remove "connector_builder_agents/" from [tool.deptry].exclude.
    Re-run deptry to confirm the warning is resolved.
🤖 Prompt for AI Agents
In pyproject.toml around lines 16-17, the pydantic-ai dependencies are listed in
the base [project] deps; move them into an optional extra named "agents" by
removing the two lines from [project] and adding them under
[project.optional-dependencies] agents = [...] with the same version
constraints, or alternatively ensure the package "connector_builder_agents" is
included in [tool.hatch.build.targets.wheel].packages and remove
"connector_builder_agents/" from [tool.deptry].exclude so the wheel build
includes that module; after making either change, re-run deptry to confirm the
warning is resolved.

- Corrected import path from pydantic_ai.common_tools.duckduckgo
- Changed to function call: duckduckgo_search_tool()
- Added [duckduckgo] optional group to pydantic-ai-slim dependency
- Added emoji as direct dependency (used in tools.py)
- Excluded connector_builder_agents/src/evals/ from Deptry scanning
- Fixes Deptry false positives for pydantic-ai package usage

Co-Authored-By: AJ Steers <[email protected]>
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: 2

🧹 Nitpick comments (1)
connector_builder_agents/src/agents.py (1)

120-120: Consider type-safe result data handling.

The conversion str(result.data) assumes result.data is present and meaningful. If result.data is None or an unexpected type, the conversion succeeds silently but may return unhelpful values like "None".

For better type safety, consider explicit handling:

-        return str(result.data)
+        if result.data is None:
+            return "Task completed (no data returned)"
+        return str(result.data)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9731ed and 2df604e.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • connector_builder_agents/src/agents.py (3 hunks)
  • pyproject.toml (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
connector_builder_agents/src/agents.py (2)
connector_builder_agents/src/tools.py (5)
  • SessionState (17-50)
  • create_log_progress_milestone_from_developer_tool (284-291)
  • create_log_problem_encountered_by_developer_tool (264-271)
  • create_log_tool_failure_tool (220-251)
  • update_progress_log (144-168)
connector_builder_agents/src/guidance.py (2)
  • get_default_developer_prompt (76-93)
  • get_default_manager_prompt (58-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
  • GitHub Check: Pytest (Fast)
🔇 Additional comments (4)
connector_builder_agents/src/agents.py (4)

4-5: LGTM: Clean migration to pydantic-ai framework.

The imports correctly replace the openai-agents framework with pydantic-ai's Agent and RunContext, and adopt the built-in duckduckgo_search_tool.


23-51: LGTM: Developer agent correctly configured.

The developer agent is properly initialized with pydantic-ai's Agent class, includes appropriate tools (progress logging, problem reporting, and web search), and correctly integrates MCP servers via the toolsets pattern.


54-85: LGTM: Manager agent properly initialized.

The manager agent configuration follows the same pydantic-ai patterns as the developer agent, with appropriate tools for orchestration and MCP server integration.


122-149: LGTM: Well-structured progress reporting mechanism.

The report_back_to_manager tool provides a clean interface for the developer agent to communicate status back to the manager with structured flags (is_full_success, is_partial_success, is_blocked) and detailed updates.

Comment on lines 106 to 120
result = await developer_agent.run(
assignment_description,
message_history=ctx.deps.message_history,
deps=ctx.deps,
)

def create_on_manager_handback(session_state: SessionState):
"""Create an on_manager_handback callback bound to a specific session state."""
update_progress_log(
f"🤝 [DEVELOPER → MANAGER] Developer completed task: {assignment_title}"
f"\n Result: {result.data}",
ctx.deps,
)

async def on_manager_handback(ctx, input_data: ManagerHandoffInput) -> None:
ctx.deps.message_history.extend(result.new_messages())

return str(result.data)
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

Add error handling for developer agent invocation.

The developer_agent.run() call at line 106 lacks error handling. If the developer agent encounters an exception, it will propagate uncaught, potentially causing the manager to fail without proper logging or recovery.

Consider wrapping the invocation in a try-except block:

-        result = await developer_agent.run(
-            assignment_description,
-            message_history=ctx.deps.message_history,
-            deps=ctx.deps,
-        )
-
-        update_progress_log(
-            f"🤝 [DEVELOPER → MANAGER] Developer completed task: {assignment_title}"
-            f"\n Result: {result.data}",
-            ctx.deps,
-        )
-
-        ctx.deps.message_history.extend(result.new_messages())
-
-        return str(result.data)
+        try:
+            result = await developer_agent.run(
+                assignment_description,
+                message_history=ctx.deps.message_history,
+                deps=ctx.deps,
+            )
+
+            update_progress_log(
+                f"🤝 [DEVELOPER → MANAGER] Developer completed task: {assignment_title}"
+                f"\n Result: {result.data}",
+                ctx.deps,
+            )
+
+            ctx.deps.message_history.extend(result.new_messages())
+
+            return str(result.data)
+        except Exception as e:
+            error_msg = f"Developer agent failed during task '{assignment_title}': {str(e)}"
+            update_progress_log(f"❌ {error_msg}", ctx.deps)
+            return f"ERROR: {error_msg}"
📝 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
result = await developer_agent.run(
assignment_description,
message_history=ctx.deps.message_history,
deps=ctx.deps,
)
def create_on_manager_handback(session_state: SessionState):
"""Create an on_manager_handback callback bound to a specific session state."""
update_progress_log(
f"🤝 [DEVELOPER → MANAGER] Developer completed task: {assignment_title}"
f"\n Result: {result.data}",
ctx.deps,
)
async def on_manager_handback(ctx, input_data: ManagerHandoffInput) -> None:
ctx.deps.message_history.extend(result.new_messages())
return str(result.data)
try:
result = await developer_agent.run(
assignment_description,
message_history=ctx.deps.message_history,
deps=ctx.deps,
)
update_progress_log(
f"🤝 [DEVELOPER → MANAGER] Developer completed task: {assignment_title}"
f"\n Result: {result.data}",
ctx.deps,
)
ctx.deps.message_history.extend(result.new_messages())
return str(result.data)
except Exception as e:
error_msg = f"Developer agent failed during task '{assignment_title}': {str(e)}"
update_progress_log(f"❌ {error_msg}", ctx.deps)
return f"ERROR: {error_msg}"

)

async def on_manager_handback(ctx, input_data: ManagerHandoffInput) -> None:
ctx.deps.message_history.extend(result.new_messages())
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

❓ Verification inconclusive

Monitor unbounded message history growth.

The message history is extended indefinitely without pruning or size limits. In long-running sessions with many delegations, this could lead to excessive memory consumption and slower performance as the context grows.

As noted in the PR objectives checklist, message history growth should be monitored. Consider implementing a mechanism to prune old messages or set a maximum history size.

Verify whether there's a history management mechanism elsewhere in the codebase:


🏁 Script executed:

#!/bin/bash
# Search for message_history pruning, cleanup, or size management
rg -n -C5 'message_history.*(?:prune|clear|trim|limit|max|size)' --type py

Length of output: 0


#!/bin/bash
# Search for all occurrences of message_history and any pruning/size-management logic
rg -n 'message_history' --type py
rg -nP '(?:message_history|history).*\b(prune|trim|limit|max|size)\b' --type py -C5

Limit message history growth.

In connector_builder_agents/src/agents.py:118, ctx.deps.message_history.extend(result.new_messages()) is unbounded. Add pruning or enforce a maximum history size to prevent unbounded memory usage.

🤖 Prompt for AI Agents
In connector_builder_agents/src/agents.py around line 118,
ctx.deps.message_history.extend(result.new_messages()) allows unbounded growth
of the message history; after extending, enforce a maximum history size (e.g., a
configurable MAX_HISTORY constant or setting) and prune older entries to keep
only the most recent N messages, or replace the list with a
collections.deque(maxlen=...) to automatically discard oldest entries — update
code to extend/add new messages then trim the list to the max length (or convert
to deque) so memory usage is bounded.

@aaronsteers
Copy link
Contributor Author

aaronsteers commented Oct 13, 2025

/build-connector

🛠️ Building connector...

Link to job logs.

❌ Poe command evals run --connector source-jsonplaceholder failed. Please inspect the logs.

The evals command was failing with ModuleNotFoundError for pydantic_ai
because the connector_builder_agents subdirectory has its own separate
package configuration that still referenced openai-agents.

- Replaced openai-agents>=0.3.3 with pydantic-ai>=0.0.14,<1.0
- Added pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0
- Removed mcp-agent (was transitive dependency of openai-agents)
- Removed openinference-instrumentation-openai-agents (openai-agents specific)
- Updated connector_builder_agents/uv.lock via uv sync

Fixes: /build-connector evals failure
Co-Authored-By: AJ Steers <[email protected]>
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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2df604e and e84bca4.

⛔ Files ignored due to path filters (1)
  • connector_builder_agents/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • connector_builder_agents/pyproject.toml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Pytest (Fast)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)

Comment on lines +9 to +10
"pydantic-ai>=0.0.14,<1.0",
"pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove the duplicate Pydantic AI distributions.

pydantic-ai and pydantic-ai-slim[...] both ship the same pydantic_ai package; installing both forces pip to pick one wheel and the other will repeatedly reinstall/overwrite during builds. Choose a single distribution (likely the slim extra) to avoid installation failures.

     "python-dotenv>=1.1.1",
-    "pydantic-ai>=0.0.14,<1.0",
     "pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0",
📝 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
"pydantic-ai>=0.0.14,<1.0",
"pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0",
"python-dotenv>=1.1.1",
"pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0",
🤖 Prompt for AI Agents
In connector_builder_agents/pyproject.toml around lines 9-10, the file lists
both "pydantic-ai" and "pydantic-ai-slim[openai,duckduckgo]" which are the same
package and conflict during installs; remove the duplicate "pydantic-ai" entry
and keep the slim distribution with the needed extras
(pydantic-ai-slim[openai,duckduckgo]>=0.0.14,<1.0), then update the lockfile
(poetry lock / pip-compile / reinstall deps) so the dependency graph reflects
the change.

@devin-ai-integration devin-ai-integration bot marked this pull request as draft October 13, 2025 01:29
@devin-ai-integration devin-ai-integration bot marked this pull request as ready for review October 13, 2025 01:29
The pydantic-ai AgentRunResult object uses 'output' attribute, not 'data'.
This was causing the evals CI check to fail with:
AttributeError: 'AgentRunResult' object has no attribute 'data'

Fixes the delegate_to_developer function in agents.py.

Co-Authored-By: AJ Steers <[email protected]>
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: 0

♻️ Duplicate comments (2)
connector_builder_agents/src/agents.py (2)

106-110: Add error handling for developer agent invocation.

The developer_agent.run() call lacks error handling. If the developer agent encounters an exception, it will propagate uncaught, potentially causing the manager to fail without proper logging or recovery.

The previous review comment on this issue remains valid and unresolved. Consider wrapping the invocation in a try-except block as suggested in the earlier review.


118-118: Limit message history growth.

The ctx.deps.message_history.extend(result.new_messages()) call allows unbounded growth. In long-running sessions with many delegations, this could lead to excessive memory consumption and performance degradation.

The previous review comment on this issue remains valid and unresolved. Consider implementing a mechanism to prune old messages or set a maximum history size as suggested in the earlier review.

🧹 Nitpick comments (1)
connector_builder_agents/src/agents.py (1)

122-150: Consider enhancing the return value.

The tool returns a static string "Status reported to manager" regardless of the status content. While functional, a more informative return value could include a summary of the reported status.

For example:

-        return "Status reported to manager"
+        return f"Reported to manager: {short_status} (full_success={is_full_success}, blocked={is_blocked})"

This would provide better context in the message history and agent logs.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e84bca4 and 96667a1.

📒 Files selected for processing (1)
  • connector_builder_agents/src/agents.py (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
connector_builder_agents/src/agents.py (2)
connector_builder_agents/src/tools.py (5)
  • SessionState (17-50)
  • create_log_progress_milestone_from_developer_tool (284-291)
  • create_log_problem_encountered_by_developer_tool (264-271)
  • create_log_tool_failure_tool (220-251)
  • update_progress_log (144-168)
connector_builder_agents/src/guidance.py (2)
  • get_default_developer_prompt (76-93)
  • get_default_manager_prompt (58-73)
🔇 Additional comments (4)
connector_builder_agents/src/agents.py (4)

4-5: LGTM!

The import changes correctly reflect the migration from openai-agents to pydantic-ai framework.


23-51: LGTM!

The developer agent setup correctly uses pydantic-ai patterns:

  • Proper return type annotation with Agent
  • Correct constructor parameters including deps_type
  • MCP servers attached via toolsets.append()
  • Web search tool updated to pydantic-ai's duckduckgo_search_tool()

54-85: LGTM!

The manager agent setup follows the same correct pydantic-ai patterns as the developer agent, with proper type annotations and MCP server attachment.


114-114: Confirm .output is correct
Pydantic-AI’s RunResult object exposes its output via the .output attribute, not .data.

@devin-ai-integration devin-ai-integration bot marked this pull request as draft October 13, 2025 01:38
@devin-ai-integration devin-ai-integration bot marked this pull request as ready for review October 13, 2025 01:38
Found three additional locations in run.py that were using result.data
instead of result.output:
- Line 143 in run_interactive_build function
- Line 224 in run_manager_developer_build function
- Line 231 in run_manager_developer_build function

This completes the migration from openai-agents to pydantic-ai.

Co-Authored-By: AJ Steers <[email protected]>
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: 1

♻️ Duplicate comments (1)
connector_builder_agents/src/run.py (1)

145-145: Previous critical issue not addressed: blocking I/O and process termination.

The blocking input() call at Line 145 and sys.exit(0) at Line 154 were flagged in the previous review but remain unresolved.

  • Line 145: input() blocks the async event loop, preventing concurrent operations.
  • Line 154: sys.exit(0) terminates the entire process ungracefully, preventing cleanup and making the function non-reusable.

Apply this diff to address both issues:

+import asyncio
+
 async def run_interactive_build(
     prompt: str,
     model: str,
     session_id: str,
 ) -> None:
     """Run the agent using interactive mode with conversation loop."""
     workspace_dir = get_workspace_dir(session_id)
     session_state = create_session_state(workspace_dir)
 
     all_mcp_servers, _, _ = create_session_mcp_servers(session_state)
     agent = Agent(
         model,
         name="MCP Connector Builder",
         deps_type=SessionState,
         system_prompt=(
             "You are a helpful assistant with access to MCP tools for building Airbyte connectors."
         ),
     )
 
     for mcp_server in all_mcp_servers:
         agent.toolsets.append(mcp_server)
 
     input_prompt: str = prompt
     while True:
         update_progress_log("\n⚙️  AI Agent is working...", session_state)
         try:
             result = await agent.run(
                 input_prompt,
                 message_history=session_state.message_history,
                 deps=session_state,
             )
 
             session_state.message_history.extend(result.new_messages())
 
             update_progress_log(f"\n🤖  AI Agent: {result.output}", session_state)
 
-            input_prompt = input("\n👤  You: ")
+            loop = asyncio.get_event_loop()
+            input_prompt = await loop.run_in_executor(None, input, "\n👤  You: ")
             if input_prompt.lower() in {"exit", "quit"}:
                 update_progress_log("☑️ Ending conversation...", session_state)
                 break
 
         except KeyboardInterrupt:
             update_progress_log(
                 "\n🛑 Conversation terminated (ctrl+c input received).", session_state
             )
-            sys.exit(0)
+            return None
 
     return None

Also applies to: 150-154

🧹 Nitpick comments (1)
connector_builder_agents/src/run.py (1)

50-50: Consider preserving type information in return signatures.

The return types have been loosened from list[RunResult] to list (Line 165) and from list[RunResult] | None to list | None (Line 50). This removes valuable type information and reduces type safety.

If RunResult is no longer available due to the framework migration, consider defining a replacement type or using a more specific type hint.

If pydantic-ai provides a result type, use it:

+from pydantic_ai import RunResult  # or equivalent
+
-) -> list | None:
+) -> list[RunResult] | None:
-) -> list:
+) -> list[RunResult]:

Also applies to: 165-165

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96667a1 and bea1241.

📒 Files selected for processing (1)
  • connector_builder_agents/src/run.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
connector_builder_agents/src/run.py (3)
connector_builder_agents/src/_util.py (1)
  • get_secrets_dotenv (29-88)
connector_builder_agents/src/agents.py (2)
  • create_developer_agent (23-51)
  • create_manager_agent (54-151)
connector_builder_agents/src/tools.py (4)
  • SessionState (17-50)
  • update_progress_log (144-168)
  • is_complete (48-50)
  • is_complete (132-134)

Comment on lines +236 to +238
except KeyboardInterrupt:
update_progress_log("\n🛑 Build terminated (ctrl+c input received).", session_state)
sys.exit(0)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Don't terminate the process in a library function.

Line 238 uses sys.exit(0) which terminates the entire process. This prevents cleanup and makes the function non-reusable as a library component.

Apply this diff to return gracefully:

     except KeyboardInterrupt:
         update_progress_log("\n🛑 Build terminated (ctrl+c input received).", session_state)
-        sys.exit(0)
+        return []
📝 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
except KeyboardInterrupt:
update_progress_log("\n🛑 Build terminated (ctrl+c input received).", session_state)
sys.exit(0)
except KeyboardInterrupt:
update_progress_log("\n🛑 Build terminated (ctrl+c input received).", session_state)
return []
🤖 Prompt for AI Agents
In connector_builder_agents/src/run.py around lines 236-238, the except block
currently calls sys.exit(0) which force-terminates the whole process; instead
remove the sys.exit call and return gracefully to the caller (or return an
appropriate sentinel value) after logging the termination message so the
function can be used as a library component and allows callers to perform
cleanup.

@devin-ai-integration devin-ai-integration bot marked this pull request as draft October 13, 2025 01:44
@devin-ai-integration devin-ai-integration bot marked this pull request as ready for review October 13, 2025 01:44
…_output

The pydantic-ai AgentRunResult object uses 'output' attribute, not 'final_output'.
This was causing the evals CI check to fail with:
AttributeError: 'AgentRunResult' object has no attribute 'final_output'

Completes the migration from openai-agents to pydantic-ai by fixing the last
remaining incompatible attribute access in the evals code.

Co-Authored-By: AJ Steers <[email protected]>
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: 0

🧹 Nitpick comments (1)
connector_builder_agents/src/evals/task.py (1)

54-54: Rename dictionary key to match attribute. The code now uses final_result.output but the result dict still uses "final_output"—consider renaming it to "output" for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bea1241 and 7d21084.

📒 Files selected for processing (1)
  • connector_builder_agents/src/evals/task.py (1 hunks)

@devin-ai-integration devin-ai-integration bot marked this pull request as draft October 13, 2025 01:53
@devin-ai-integration devin-ai-integration bot marked this pull request as ready for review October 13, 2025 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant