Skip to content

refactor(models): Refine MessageAgentThought SQLAlchemy typing#11

Open
tomerqodo wants to merge 2 commits intocoderabbit_full_base_refactormodels_refine_messageagentthought_sqlalchemy_typing_pr11from
coderabbit_full_head_refactormodels_refine_messageagentthought_sqlalchemy_typing_pr11
Open

refactor(models): Refine MessageAgentThought SQLAlchemy typing#11
tomerqodo wants to merge 2 commits intocoderabbit_full_base_refactormodels_refine_messageagentthought_sqlalchemy_typing_pr11from
coderabbit_full_head_refactormodels_refine_messageagentthought_sqlalchemy_typing_pr11

Conversation

@tomerqodo
Copy link
Copy Markdown

@tomerqodo tomerqodo commented Jan 30, 2026

Benchmark PR from agentic-review-benchmarks#11

Summary by CodeRabbit

Release Notes

  • New Features

    • Added validation for agent thought data to ensure consistency and reliability across records.
  • Bug Fixes

    • Improved precision in pricing calculations for agent interactions to prevent rounding errors.
  • Refactor

    • Enhanced the persistence and organization of agent thoughts for more robust data handling.
    • Improved field structure for agent interaction records with better type consistency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 30, 2026

📝 Walkthrough

Walkthrough

This pull request introduces stricter data validation and type safety for agent thought persistence. Changes include a new validation model for agent thoughts, restructured database schema for the MessageAgentThought entity with explicit field typing and defaults, improved monetary field handling using Decimal, and refactored tool history parsing logic. Test fixtures are updated to rely on auto-generated IDs.

Changes

Cohort / File(s) Summary
Agent Core Logic
api/core/agent/base_agent_runner.py
Introduces AgentThoughtValidation Pydantic model for validating agent thought data. Enhances numeric handling with Decimal types, switches created_by_role to enum value, extends agent thought creation with tool_process_data field, and reworks tool history parsing with per-tool input/observation handling and robust JSON fallbacks.
Data Model
api/models/model.py
Updates MessageAgentThought class hierarchy from Base to TypeBase. Adds explicit field typing with Mapped annotations, introduces created_by_role, created_by, message_chain_id fields, converts monetary fields to Decimal, and replaces untyped string fields with structured typed equivalents including server defaults and init flags.
Test Fixtures
api/tests/.../services/test_agent_service.py
Removes explicit id=fake.uuid4() assignments from MessageAgentThought test constructions, allowing ORM auto-generation of IDs instead of manual assignment.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Thoughts now validated, fields all typed with care,
Decimals for prices, metadata everywhere,
Tool histories parsed with logic so tight,
Agent minds structured—what a delight!
IDs auto-generated, constraints in place,
Better data flows through the codebase.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and only references a benchmark PR without providing a substantive summary, motivation, or context about the changes. Add a detailed summary section explaining what was changed, why it was changed, and any relevant context or dependencies. Follow the template structure with proper sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: refactoring MessageAgentThought with improved SQLAlchemy typing and field definitions.

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

✨ 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 coderabbit_full_head_refactormodels_refine_messageagentthought_sqlalchemy_typing_pr11

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 and usage tips.

@tomerqodo
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 30, 2026

✅ Actions performed

Review triggered.

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

@tomerqodo
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 30, 2026

✅ Actions performed

Review triggered.

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

@tomerqodo
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 30, 2026

✅ Actions performed

Review triggered.

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

@ravidqodo
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 2, 2026

✅ Actions performed

Review triggered.

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

@ravidqodo
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 2, 2026

✅ Actions performed

Review triggered.

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

Copy link
Copy Markdown

@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

Caution

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

⚠️ Outside diff range comments (1)
api/core/agent/base_agent_runner.py (1)

500-506: ⚠️ Potential issue | 🔴 Critical

Bug: tool_call_response should use tool_responses, not tool_inputs.

The ToolPromptMessage represents the tool's response/output, but line 502 retrieves content from tool_inputs instead of tool_responses. This causes the tool response to incorrectly contain the input data rather than the actual observation/output.

Proposed fix
                             tool_call_response.append(
                                 ToolPromptMessage(
-                                    content=str(tool_inputs.get(tool, agent_thought.observation)),
+                                    content=str(tool_responses.get(tool, agent_thought.observation)),
                                     name=tool,
                                     tool_call_id=tool_call_id,
                                 )
                             )
🤖 Fix all issues with AI agents
In `@api/core/agent/base_agent_runner.py`:
- Around line 319-328: The answer_* and message_* price fields are likely
swapped and total_price has wrong type: in the initialization inside
BaseAgentRunner (or the class/constructor where message_unit_price,
message_price_unit, answer_unit_price, answer_price_unit are set) swap the
values so message_unit_price and answer_unit_price are Decimal(0) and
message_price_unit and answer_price_unit are Decimal("0.001"); also change
total_price from int 0 to a Decimal(0) (or None) to match the declared type
Mapped[Decimal | None]. Ensure you update the initialization of
answer_unit_price, answer_price_unit, message_unit_price, message_price_unit,
and total_price accordingly.
🧹 Nitpick comments (2)
api/models/model.py (1)

1856-1857: Consider using plain Python strings for defaults instead of sa.text().

Using sa.text("'{}'") as the default parameter is unconventional. While SQLAlchemy 2.0 accepts SQL expressions for client-side defaults, a plain Python string "{}" would be simpler and more readable. The sa.text() approach is typically reserved for server_default.

Suggested simplification
-    tool_labels_str: Mapped[str] = mapped_column(LongText, nullable=False, default=sa.text("'{}'"))
-    tool_meta_str: Mapped[str] = mapped_column(LongText, nullable=False, default=sa.text("'{}'"))
+    tool_labels_str: Mapped[str] = mapped_column(LongText, nullable=False, default="{}")
+    tool_meta_str: Mapped[str] = mapped_column(LongText, nullable=False, default="{}")
api/core/agent/base_agent_runner.py (1)

52-66: Update AgentThoughtValidation to Pydantic v2 syntax.

The model uses deprecated Pydantic v1 class Config syntax. With pydantic 2.11.4, use model_config = ConfigDict(extra="allow") instead:

from pydantic import BaseModel, ConfigDict

class AgentThoughtValidation(BaseModel):
    """
    Validation model for agent thought data before database persistence.
    """

    message_id: str
    position: int
    thought: str | None = None
    tool: str | None = None
    tool_input: str | None = None
    observation: str | None = None

    model_config = ConfigDict(extra="allow")

This model is not referenced anywhere in the codebase—confirm if this is intentional or if integration is missing.

Comment on lines +319 to 328
message_unit_price=Decimal(0),
message_price_unit=Decimal("0.001"),
message_files=json.dumps(messages_ids) if messages_ids else "",
answer="",
observation="",
answer_token=0,
answer_unit_price=0,
answer_price_unit=0,
answer_unit_price=Decimal("0.001"),
answer_price_unit=Decimal(0),
tokens=0,
total_price=0,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Verify answer_unit_price and answer_price_unit values are not swapped.

The initialization values appear inconsistent between message and answer fields:

Field message_* answer_*
unit_price Decimal(0) Decimal("0.001")
price_unit Decimal("0.001") Decimal(0)

Typically, *_price_unit represents the unit size (e.g., 0.001 for per-1000 tokens) and should be non-zero, while *_unit_price is the actual price which starts at 0. The answer fields appear to have these values swapped.

Also, total_price=0 should be Decimal(0) or None for type consistency with Mapped[Decimal | None].

Suggested fix
         message_unit_price=Decimal(0),
         message_price_unit=Decimal("0.001"),
         message_files=json.dumps(messages_ids) if messages_ids else "",
         answer="",
         observation="",
         answer_token=0,
-        answer_unit_price=Decimal("0.001"),
-        answer_price_unit=Decimal(0),
+        answer_unit_price=Decimal(0),
+        answer_price_unit=Decimal("0.001"),
         tokens=0,
-        total_price=0,
+        total_price=Decimal(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
message_unit_price=Decimal(0),
message_price_unit=Decimal("0.001"),
message_files=json.dumps(messages_ids) if messages_ids else "",
answer="",
observation="",
answer_token=0,
answer_unit_price=0,
answer_price_unit=0,
answer_unit_price=Decimal("0.001"),
answer_price_unit=Decimal(0),
tokens=0,
total_price=0,
message_unit_price=Decimal(0),
message_price_unit=Decimal("0.001"),
message_files=json.dumps(messages_ids) if messages_ids else "",
answer="",
observation="",
answer_token=0,
answer_unit_price=Decimal(0),
answer_price_unit=Decimal("0.001"),
tokens=0,
total_price=Decimal(0),
🤖 Prompt for AI Agents
In `@api/core/agent/base_agent_runner.py` around lines 319 - 328, The answer_* and
message_* price fields are likely swapped and total_price has wrong type: in the
initialization inside BaseAgentRunner (or the class/constructor where
message_unit_price, message_price_unit, answer_unit_price, answer_price_unit are
set) swap the values so message_unit_price and answer_unit_price are Decimal(0)
and message_price_unit and answer_price_unit are Decimal("0.001"); also change
total_price from int 0 to a Decimal(0) (or None) to match the declared type
Mapped[Decimal | None]. Ensure you update the initialization of
answer_unit_price, answer_price_unit, message_unit_price, message_price_unit,
and total_price accordingly.

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