Skip to content

added ambiguity node after schema explorer - #26

Merged
yuvalkh merged 5 commits into
mainfrom
yuval/detect-ambiguity
Jul 23, 2026
Merged

added ambiguity node after schema explorer#26
yuvalkh merged 5 commits into
mainfrom
yuval/detect-ambiguity

Conversation

@yuvalkh

@yuvalkh yuvalkh commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added automatic ambiguity detection before SQL generation, with an interactive clarification flow and capped retries.
    • If a request can’t be resolved, the agent now returns an explicit unanswerable outcome that’s reflected in the chat response and the testing interface.
  • Bug Fixes
    • Improved satisfaction-check behavior for answers that only include the directly requested fields.
    • Enhanced formatting of agent/judge failure details and improved handling when resuming agent sessions.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The agent adds a dedicated ambiguity-detection and HITL clarification path before SQL generation, with retry limits and unanswerable outcomes. API and frontend contracts expose this status, while schema exploration, diagnostic messages, and profiling endpoint handling are updated.

Changes

Ambiguity workflow

Layer / File(s) Summary
Ambiguity contracts and schema exploration
agent/scripts/upload_all_prompts.py, agent/src/agent/config.py, agent/src/agent/state.py, agent/src/agent/nodes/schema_explorer.py, agent/src/agent/utils/schema_enrichment.py
A dedicated ambiguity prompt, state fields, retry settings, and simplified schema-explorer output replace the previous inline ambiguity handling.
Ambiguity detection and clarification nodes
agent/src/agent/nodes/detect_ambiguity.py
Structured LLM classification produces clear, ambiguous, or unanswerable outcomes, while HITL clarification updates the query and retries schema exploration.
Graph routing and resume integration
agent/src/agent/graph.py, agent/src/agent/mcp_server.py
The graph adds ambiguity routing and interruption points; resumed feedback is mapped into state and final responses include unanswerable status.
Unanswerable response presentation
backend/app/routers/agent.py, frontend/src/api/agent.ts, frontend/src/pages/AgentTestingPage.tsx
The response contract carries is_unanswerable, and the testing page renders a failure state while creating fresh thread IDs.
Diagnostic prompt and failure formatting
agent/src/agent/nodes/satisfaction_check.py, agent/src/agent/nodes/refiner.py
Satisfaction prompts allow exact requested-column results, and failure details use multiline bullet formatting.

Profiling endpoint handling

Layer / File(s) Summary
Profiling execution and response handling
backend/app/routers/profiling.py, backend/app/infra_init.py, frontend/src/components/tables/ProfilingTab.tsx, frontend/src/types/index.ts
Profiling response construction and Temporal error handling are updated; related frontend formatting and an import order are adjusted without changing profiling controls.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MCPServer
  participant SchemaExplorer
  participant DetectAmbiguity
  participant AmbiguityResolution
  participant QueryBuilder
  User->>MCPServer: Submit request
  MCPServer->>SchemaExplorer: Execute schema exploration
  SchemaExplorer->>DetectAmbiguity: schema_plan and schema context
  DetectAmbiguity->>QueryBuilder: Clear result
  DetectAmbiguity->>AmbiguityResolution: Ambiguous result and questions
  User->>MCPServer: Provide clarification
  MCPServer->>AmbiguityResolution: Resume with feedback
  AmbiguityResolution->>SchemaExplorer: Retry with updated user_query
  DetectAmbiguity-->>MCPServer: Unanswerable result
  MCPServer-->>User: is_unanswerable response
Loading

Possibly related PRs

Suggested reviewers: benben-ship-it

Poem

A rabbit found a query unclear,
And asked for a hint from far and near.
The graph paused, then hopped anew,
With retries counted—one, then two.
Clear SQL sprang from the plan,
Or “unanswerable” told the clan.

🚥 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 accurately summarizes the main change: adding an ambiguity node after schema explorer.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
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 yuval/detect-ambiguity

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: 2

🤖 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 `@agent/src/agent/nodes/detect_ambiguity.py`:
- Around line 155-165: Update the parse-failure fallback in detect_ambiguity to
use a generic user-facing clarification in the reason field, preventing raw
exception details from reaching downstream clarifying-question output. Keep the
captured exception available only through logging or internal ambiguity_result
data, while preserving the existing ambiguous classification.

In `@agent/src/agent/nodes/schema_explorer.py`:
- Around line 525-529: Update the exception fallback in the schema explorer
parsing flow to construct SchemaExplorerOutput with an empty string (or the
model’s valid default) for schema_plan instead of None. Preserve the existing
plan = data.schema_plan or "" recovery behavior so parsing failures return
normally without triggering another validation error.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 26a079bf-e99e-4260-b056-0974e018258d

📥 Commits

Reviewing files that changed from the base of the PR and between 45b5194 and 6fd396d.

📒 Files selected for processing (14)
  • agent/scripts/upload_all_prompts.py
  • agent/src/agent/config.py
  • agent/src/agent/graph.py
  • agent/src/agent/mcp_server.py
  • agent/src/agent/nodes/detect_ambiguity.py
  • agent/src/agent/nodes/refiner.py
  • agent/src/agent/nodes/satisfaction_check.py
  • agent/src/agent/nodes/schema_explorer.py
  • agent/src/agent/state.py
  • agent/src/agent/utils/flag_bridge.py
  • agent/src/agent/utils/schema_enrichment.py
  • backend/app/routers/agent.py
  • frontend/src/api/agent.ts
  • frontend/src/pages/AgentTestingPage.tsx
💤 Files with no reviewable changes (1)
  • agent/src/agent/utils/flag_bridge.py

Comment thread agent/src/agent/nodes/detect_ambiguity.py
Comment thread agent/src/agent/nodes/schema_explorer.py
Comment thread agent/src/agent/utils/flag_bridge.py
Comment thread agent/src/agent/nodes/detect_ambiguity.py

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
agent/src/agent/nodes/detect_ambiguity.py (1)

263-274: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Pass the fallback clarification via feedback so it reaches schema_explorer.

When the user provides no feedback, the code constructs user_feedback with the previous question but then explicitly omits it from new_query and sets "feedback": None. This discards the fallback context entirely, leaving schema_explorer with the exact same inputs as the previous run. This will result in a loop of identical outputs until max retries are hit.

Pass the fallback context via the feedback state field so schema_explorer can use it. The downstream sql_static_validations_node will safely clear it before it reaches the rejection_router.

🐛 Proposed fix
     new_query = state.get("user_query", "")
     if user_feedback and not user_feedback.startswith("[Previous"):
         new_query += f"\n[User Clarification: {user_feedback}]"
 
     return {
         # Update the main query so all subsequent nodes see the unified intent.
         "user_query": new_query,
         # Clear ambiguity decision so detect_ambiguity re-evaluates cleanly on retry.
         "ambiguity_type": None,
         "ambiguity_result": None,
         "clarifying_questions": None,
-        # Clear feedback so it doesn't accidentally trigger the rejection_router later.
-        "feedback": None,
+        # Pass the previous question as feedback if no user clarification was provided;
+        # sql_static_validations_node will safely clear it later.
+        "feedback": user_feedback if user_feedback.startswith("[Previous") else None,
         "ambiguity_retry_count": retry_count,
         "execution_path": ["ambiguity_resolution"],
     }
🤖 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 `@agent/src/agent/nodes/detect_ambiguity.py` around lines 263 - 274, Update the
retry return state in the ambiguity-handling flow to preserve the constructed
fallback user_feedback through the "feedback" field instead of setting it to
None. Keep the existing new_query behavior for explicit feedback, and ensure
schema_explorer receives the fallback clarification while downstream validation
clears it before rejection routing.
🤖 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 `@agent/src/agent/nodes/detect_ambiguity.py`:
- Around line 157-166: Update the exception fallback result in the ambiguity
detection flow to include only the current AmbiguityResult fields:
ambiguity_type, reason, and clarifying_questions. Remove intent_deconstruction,
active_schema_search, ambiguity_check, logical_sql_plan, and
schema_alignment_check from the parsed fallback.

---

Outside diff comments:
In `@agent/src/agent/nodes/detect_ambiguity.py`:
- Around line 263-274: Update the retry return state in the ambiguity-handling
flow to preserve the constructed fallback user_feedback through the "feedback"
field instead of setting it to None. Keep the existing new_query behavior for
explicit feedback, and ensure schema_explorer receives the fallback
clarification while downstream validation clears it before rejection routing.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 43eabab8-5f21-4f33-8c74-0657b5e4be95

📥 Commits

Reviewing files that changed from the base of the PR and between 6fd396d and 4952fc7.

📒 Files selected for processing (2)
  • agent/src/agent/nodes/detect_ambiguity.py
  • agent/src/agent/nodes/schema_explorer.py

Comment thread agent/src/agent/nodes/detect_ambiguity.py

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
agent/src/agent/config.py (1)

46-46: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep ambiguity detection disabled until its Langfuse prompt is guaranteed to exist. ENABLE_AMBIGUITY_DETECT defaults to True, so upgrades without text2sql/detect_ambiguity will route into detect_ambiguity and raise at request time. Either leave the default off until rollout is complete or provision/validate the prompt at startup.

🤖 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 `@agent/src/agent/config.py` at line 46, Update the ambiguity-detection
configuration around ENABLE_AMBIGUITY_DETECT so it defaults to disabled until
the Langfuse prompt identified by LANGFUSE_PROMPT_DETECT_AMBIGUITY is guaranteed
to exist; alternatively, add startup validation/provisioning that verifies this
prompt before enabling the feature.
🤖 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 `@agent/src/agent/config.py`:
- Line 73: Update the MAX_AMBIGUITY_RETRIES configuration field to use
validation with a default of 2 and a minimum value of 0, rejecting negative
environment-configured values while preserving zero as valid. Leave the existing
ambiguity retry handling unchanged.

---

Outside diff comments:
In `@agent/src/agent/config.py`:
- Line 46: Update the ambiguity-detection configuration around
ENABLE_AMBIGUITY_DETECT so it defaults to disabled until the Langfuse prompt
identified by LANGFUSE_PROMPT_DETECT_AMBIGUITY is guaranteed to exist;
alternatively, add startup validation/provisioning that verifies this prompt
before enabling the feature.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9b709a29-07df-45ab-923c-ef166ba17b9c

📥 Commits

Reviewing files that changed from the base of the PR and between 4952fc7 and b880a84.

📒 Files selected for processing (3)
  • agent/src/agent/config.py
  • agent/src/agent/graph.py
  • agent/src/agent/nodes/detect_ambiguity.py
💤 Files with no reviewable changes (1)
  • agent/src/agent/nodes/detect_ambiguity.py

Comment thread agent/src/agent/config.py
@yuvalkh
yuvalkh merged commit a215c19 into main Jul 23, 2026
1 check was pending

@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: 3

Caution

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

⚠️ Outside diff range comments (6)
agent/src/agent/nodes/schema_explorer.py (2)

525-533: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Do not treat schema-explorer failures as an empty successful plan.

The except block catches every structured-output/LLM failure and returns empty schema_plan and tables_used. route_schema_explorer only retries or escalates when hallucinated_tables is populated, so this path can proceed to SQL generation without schema context. Propagate an explicit failure that routes to retry/HITL instead of returning a valid-looking empty result.

🤖 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 `@agent/src/agent/nodes/schema_explorer.py` around lines 525 - 533, Update the
structured-output exception handling in the schema explorer flow to propagate an
explicit failure instead of constructing an empty SchemaExplorerOutput. Ensure
route_schema_explorer receives the failure through its existing retry or HITL
escalation path, preventing SQL generation from continuing with an empty
schema_plan and tables_used.

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

Use consistent nullable RunnableConfig contracts across nodes.

Each affected node defaults config to None and handles the missing value, but annotates it as non-nullable. Change these signatures to RunnableConfig | None = None, or require config consistently.

  • agent/src/agent/nodes/schema_explorer.py#L309-L311: update schema_explorer_node.
  • agent/src/agent/nodes/schema_explorer.py#L540-L540: update sql_static_validations_node.
  • agent/src/agent/nodes/satisfaction_check.py#L40-L47: update satisfaction_check_node.
🤖 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 `@agent/src/agent/nodes/schema_explorer.py` around lines 309 - 311, Use
consistent nullable RunnableConfig contracts by changing the config parameter
annotation to RunnableConfig | None = None in schema_explorer_node and
sql_static_validations_node in agent/src/agent/nodes/schema_explorer.py (lines
309-311 and 540), and satisfaction_check_node in
agent/src/agent/nodes/satisfaction_check.py (lines 40-47). Preserve the existing
missing-config handling.
backend/app/routers/profiling.py (3)

242-264: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Honor the force request parameter.

ProfilingTab sends force: true for “Restart from Start” and “Re-profile”, but this endpoint never reads force; only resume_from_partial is passed to Temporal. These actions cannot implement their advertised cache/restart semantics.

🤖 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 `@backend/app/routers/profiling.py` around lines 242 - 264, Update
run_table_profile to honor the force parameter by propagating it through
trigger_temporal_profiling_workflow and the underlying profiling workflow
invocation. Ensure forced requests bypass the 24-hour cache and restart from the
beginning, while preserving resume_from_partial behavior for non-forced
requests.

258-264: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Avoid duplicate run rows for an already-running workflow.

Every request inserts a new pending ProfilingRun, while WorkflowAlreadyStartedError is treated as success for the same fixed workflow ID. A second request therefore creates a synthetic latest run without starting a new execution. Reuse the existing active run or associate each database run with its workflow execution.

🤖 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 `@backend/app/routers/profiling.py` around lines 258 - 264, Update the
profiling request flow around ProfilingRun creation and
trigger_temporal_profiling_workflow so repeated requests for an already-running
workflow do not insert a new pending row. Before creating a run, locate and
reuse the existing active run for the fixed workflow ID, or associate the new
run with a distinct execution ID; ensure WorkflowAlreadyStartedError continues
to reference the actual active run rather than a synthetic latest row.

326-338: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not mark profiling cancellation complete until the workflow is terminal.

handle.cancel() only requests cancellation, but TableProfilingWorkflow.run() catches asyncio.CancelledError and then runs persist_profiling_results_activity(), which persists the partial profile and can finalize the run as completed. The router currently writes ProfilingStatus.canceled immediately; make the worker’s final terminal update authoritative or poll until Temporal reports a terminal state before updating the run status.

🤖 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 `@backend/app/routers/profiling.py` around lines 326 - 338, The profiling
cancellation flow around handle.cancel() must not immediately set
latest_run.status to canceled, because the worker may still persist results and
finalize the run. Remove the immediate status update and make
TableProfilingWorkflow.run()’s final terminal update authoritative, or poll the
workflow handle until Temporal reports a terminal state before committing
cancellation; preserve the existing error handling.
backend/app/infra_init.py (1)

1194-1194: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include column-level failures in the partial calculation.

run_table_profiling records failures in ColumnStats.errors, while result.success remains true for non-empty tables and result.errors may remain empty. This expression can therefore persist is_partial=False for an incomplete profile.

🤖 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 `@backend/app/infra_init.py` at line 1194, Update the is_partial assignment in
run_table_profiling to also detect column-level failures recorded in
ColumnStats.errors, while preserving the existing result.success and
result.errors checks. Ensure any non-empty column error collection marks the
profile as partial.
♻️ Duplicate comments (1)
agent/src/agent/config.py (1)

78-81: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject negative ambiguity retry limits.

MAX_AMBIGUITY_RETRIES is environment-configurable but accepts negative values. Since detect_ambiguity.py checks retry_count >= settings.MAX_AMBIGUITY_RETRIES, any negative value makes every ambiguous request immediately unanswerable. Use Field(default=2, ge=0).

🤖 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 `@agent/src/agent/config.py` around lines 78 - 81, Constrain the
environment-configurable MAX_AMBIGUITY_RETRIES setting in the configuration
model to a nonnegative integer by declaring it with Field(default=2, ge=0),
preserving the existing default and preventing negative retry limits.
🤖 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 `@backend/app/routers/profiling.py`:
- Around line 330-334: Update the exception handling around the Temporal
workflow cancellation to keep logging the detailed exception server-side, but
replace the HTTPException detail with a stable generic message instead of
interpolating str(e). Preserve the 500 status and the existing cancellation
failure context in the server log.
- Around line 180-197: Align the pending profile sentinel with ProfilingTab’s
frontend checks by updating the row_count condition used for progress and
failure panels to treat both null and undefined as absent. Apply the same
adjustment to the additional check around the profile stub handling, while
preserving existing behavior for populated row counts.
- Around line 180-200: Update both response paths in the profiling handler to
include is_partial=False in the fallback profile stub, while preserving the
persisted is_partial value from profile.model_dump() for real profiles. Remove
the unconditional is_partial=False keyword from both TableProfileRead
constructions so stored values are not overwritten and duplicate-keyword errors
cannot occur.

---

Outside diff comments:
In `@agent/src/agent/nodes/schema_explorer.py`:
- Around line 525-533: Update the structured-output exception handling in the
schema explorer flow to propagate an explicit failure instead of constructing an
empty SchemaExplorerOutput. Ensure route_schema_explorer receives the failure
through its existing retry or HITL escalation path, preventing SQL generation
from continuing with an empty schema_plan and tables_used.
- Around line 309-311: Use consistent nullable RunnableConfig contracts by
changing the config parameter annotation to RunnableConfig | None = None in
schema_explorer_node and sql_static_validations_node in
agent/src/agent/nodes/schema_explorer.py (lines 309-311 and 540), and
satisfaction_check_node in agent/src/agent/nodes/satisfaction_check.py (lines
40-47). Preserve the existing missing-config handling.

In `@backend/app/infra_init.py`:
- Line 1194: Update the is_partial assignment in run_table_profiling to also
detect column-level failures recorded in ColumnStats.errors, while preserving
the existing result.success and result.errors checks. Ensure any non-empty
column error collection marks the profile as partial.

In `@backend/app/routers/profiling.py`:
- Around line 242-264: Update run_table_profile to honor the force parameter by
propagating it through trigger_temporal_profiling_workflow and the underlying
profiling workflow invocation. Ensure forced requests bypass the 24-hour cache
and restart from the beginning, while preserving resume_from_partial behavior
for non-forced requests.
- Around line 258-264: Update the profiling request flow around ProfilingRun
creation and trigger_temporal_profiling_workflow so repeated requests for an
already-running workflow do not insert a new pending row. Before creating a run,
locate and reuse the existing active run for the fixed workflow ID, or associate
the new run with a distinct execution ID; ensure WorkflowAlreadyStartedError
continues to reference the actual active run rather than a synthetic latest row.
- Around line 326-338: The profiling cancellation flow around handle.cancel()
must not immediately set latest_run.status to canceled, because the worker may
still persist results and finalize the run. Remove the immediate status update
and make TableProfilingWorkflow.run()’s final terminal update authoritative, or
poll the workflow handle until Temporal reports a terminal state before
committing cancellation; preserve the existing error handling.

---

Duplicate comments:
In `@agent/src/agent/config.py`:
- Around line 78-81: Constrain the environment-configurable
MAX_AMBIGUITY_RETRIES setting in the configuration model to a nonnegative
integer by declaring it with Field(default=2, ge=0), preserving the existing
default and preventing negative retry limits.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 25861bea-493f-440d-aab9-7f66330056a1

📥 Commits

Reviewing files that changed from the base of the PR and between b880a84 and 78ee30c.

📒 Files selected for processing (8)
  • agent/src/agent/config.py
  • agent/src/agent/nodes/satisfaction_check.py
  • agent/src/agent/nodes/schema_explorer.py
  • agent/src/agent/state.py
  • backend/app/infra_init.py
  • backend/app/routers/profiling.py
  • frontend/src/components/tables/ProfilingTab.tsx
  • frontend/src/types/index.ts

Comment on lines +180 to +197
profile_dict = (
profile.model_dump()
if profile
else {
"id": "pending",
"table_id": table_id,
"row_count": None,
"sample_size": None,
"column_count": None,
"size_bytes": None,
"null_rate_avg": None,
"duplicate_rate": None,
"sample_data": None,
"profile_json": None,
"cached_until": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
}

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 | 🟡 Minor | ⚡ Quick win

Align the pending sentinel with the frontend checks.

The stub serializes row_count as null, but ProfilingTab checks profile?.row_count === undefined for its progress and failure panels. Consequently, pending/failed stub responses render neither panel. Use a consistent sentinel, such as row_count == null in the frontend.

Also applies to: 279-296

🤖 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 `@backend/app/routers/profiling.py` around lines 180 - 197, Align the pending
profile sentinel with ProfilingTab’s frontend checks by updating the row_count
condition used for progress and failure panels to treat both null and undefined
as absent. Apply the same adjustment to the additional check around the profile
stub handling, while preserving existing behavior for populated row counts.

Comment on lines +180 to +200
profile_dict = (
profile.model_dump()
if profile
else {
"id": "pending",
"table_id": table_id,
"row_count": None,
"sample_size": None,
"column_count": None,
"size_bytes": None,
"null_rate_avg": None,
"duplicate_rate": None,
"sample_data": None,
"profile_json": None,
"cached_until": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
}
)

return TableProfileRead(**profile_dict, status=status, is_partial=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve the persisted partial-profile state.

Both responses force is_partial=False, even though backend/app/infra_init.py now computes and stores that flag and the frontend uses it to expose retry actions. If model_dump() includes is_partial, this also raises a duplicate-keyword error. Default the stub to False, but preserve the stored value for real profiles.

Proposed fix
-    return TableProfileRead(**profile_dict, status=status, is_partial=False)
+    profile_dict.setdefault("is_partial", False)
+    return TableProfileRead(**profile_dict, status=status)

Apply the same change to both response paths.

Also applies to: 279-301

🤖 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 `@backend/app/routers/profiling.py` around lines 180 - 200, Update both
response paths in the profiling handler to include is_partial=False in the
fallback profile stub, while preserving the persisted is_partial value from
profile.model_dump() for real profiles. Remove the unconditional
is_partial=False keyword from both TableProfileRead constructions so stored
values are not overwritten and duplicate-keyword errors cannot occur.

Comment on lines 330 to +334
except Exception as e:
logger.warning(f"Failed to cancel temporal workflow for {table_id}: {e}")
raise HTTPException(status_code=500, detail=f"Failed to cancel temporal workflow: {e}")
raise HTTPException(
status_code=500, detail=f"Failed to cancel temporal workflow: {e}"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Do not expose raw Temporal errors to clients.

Returning str(e) in the HTTP detail can leak internal transport, host, or workflow information. Log the exception server-side and return a stable generic error response.

🤖 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 `@backend/app/routers/profiling.py` around lines 330 - 334, Update the
exception handling around the Temporal workflow cancellation to keep logging the
detailed exception server-side, but replace the HTTPException detail with a
stable generic message instead of interpolating str(e). Preserve the 500 status
and the existing cancellation failure context in the server log.

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