-
Notifications
You must be signed in to change notification settings - Fork 692
refactor: move agent template rendering from model to core layer #929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors agent template rendering by moving the logic from the model layer to a new core layer. The main goal is to achieve cleaner separation of concerns by having template rendering handled at the application/core level rather than within the ORM models.
Key Changes:
- New
get_agent()function inintentkit/core/agent.pythat retrieves agents and applies template rendering - New
intentkit/core/template.pymodule withrender_agent()andcreate_template_from_agent()functions - Deprecated
Agent.get()method with a deprecation warning pointing to the new function - Replaced all external calls to
Agent.get()with the newget_agent()function across 10+ files - Added new database columns
template_idandextra_prompttoAgentTable - Created new
TemplateandTemplateTablemodels extendingAgentCore
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
intentkit/models/template.py |
New template models (Template, TemplateTable) that extend AgentCore with template-specific fields |
intentkit/models/agent.py |
Added template_id and extra_prompt columns to AgentTable; added from_template_id and extra_prompt fields to AgentCreate; deprecated Agent.get() method; moved short_term_memory_strategy into AgentCore |
intentkit/core/template.py |
New module with template rendering logic: render_agent() applies template fields to agents, create_template_from_agent() creates templates from agents |
intentkit/core/agent.py |
New get_agent() function that retrieves agents and applies template rendering if template_id is set |
intentkit/core/manager/service.py |
Migrated from Agent.get() to get_agent() |
intentkit/core/engine.py |
Migrated from Agent.get() to get_agent() in multiple locations |
intentkit/core/draft.py |
Migrated from Agent.get() to get_agent() |
intentkit/core/credit.py |
Migrated from Agent.get() to get_agent() |
intentkit/core/asset.py |
Migrated from Agent.get() to get_agent() |
app/services/twitter/oauth2_callback.py |
Migrated from Agent.get() to get_agent() |
app/entrypoints/web.py |
Migrated from Agent.get() to get_agent() in 9 endpoint handlers |
app/entrypoints/openai_compatible.py |
Migrated from Agent.get() to get_agent() |
app/entrypoints/agent_api.py |
Migrated from Agent.get() to get_agent() in 7 endpoint handlers |
app/admin/api.py |
Migrated from Agent.get() to get_agent() (aliased as get_agent_by_id) in 6 locations |
intentkit/utils/slack_alert.py |
Added explicit -> None return type annotation; changed to discard response instead of returning it |
CHANGELOG.md |
Added v0.8.37 changelog entry (appears unrelated to this PR) |
Comments suppressed due to low confidence (10)
app/admin/api.py:80
- This comment appears to contain commented-out code.
# if not input.owner:
# raise IntentKitAPIError(
# status_code=400, key="BadRequest", message="Owner is required"
app/admin/api.py:88
- This comment appears to contain commented-out code.
# if user_id:
# if input.owner != user_id:
# raise IntentKitAPIError(
# status_code=400,
# key="BadRequest",
# message="Owner does not match user ID",
app/admin/api.py:95
- This comment appears to contain commented-out code.
# if user:
# max_fee += user.nft_count * 10
# if input.fee_percentage and input.fee_percentage > max_fee:
# raise IntentKitAPIError(
# status_code=400, key="BadRequest", message="Fee percentage too high"
app/admin/api.py:130
- This comment appears to contain commented-out code.
# if not input.owner:
# raise IntentKitAPIError(
# status_code=400, key="BadRequest", message="Owner is required"
app/admin/api.py:138
- This comment appears to contain commented-out code.
# if user_id:
# if input.owner != user_id:
# raise IntentKitAPIError(
# status_code=400,
# key="BadRequest",
# message="Owner does not match user ID",
app/admin/api.py:657
- Variable latest_agent is not used.
latest_agent, agent_data = await deploy_agent(agent_id, agent, "admin")
app/admin/api.py:657
- Variable agent_data is not used.
latest_agent, agent_data = await deploy_agent(agent_id, agent, "admin")
intentkit/core/engine.py:560
- Variable last is not used.
last = this_time
intentkit/core/engine.py:808
- Variable last is not used.
last = this_time
intentkit/models/agent.py:752
- This import of module re is redundant, as it was previously imported on line 6.
import re
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| thread_ts: str | None = None, | ||
| channel: str | None = None, | ||
| ): | ||
| ) -> None: |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function signature change from returning an implicit None to explicitly declaring -> None is good, but this also removes the ability for callers to check if the message was successfully sent by examining the response. The previous code returned the Slack API response which could be useful for debugging or confirmation. If callers don't need this information, this change is fine, but it's a breaking change for any code that uses the return value.
|
|
||
| short_term_memory_strategy: Annotated[ | ||
| Literal["trim", "summarize"] | None, | ||
| # only when wallet privder is readonly |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling error in comment: "privder" should be "provider".
| # only when wallet privder is readonly | |
| # only when wallet provider is readonly |
| short_term_memory_strategy: Annotated[ | ||
| Literal["trim", "summarize"] | None, | ||
| PydanticField( | ||
| default=None, | ||
| description="Provider of the agent's wallet", | ||
| default="trim", | ||
| description="Strategy for managing short-term memory when context limit is reached. 'trim' removes oldest messages, 'summarize' creates summaries.", | ||
| ), | ||
| ] |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The short_term_memory_strategy field was moved from AgentUserInput to AgentCore. This means it will now be included in template rendering and agent hash calculations. This is a significant behavioral change that should be explicitly mentioned in the PR description and tested. Verify that this is the intended behavior, as it changes the scope of which fields are considered "core" to an agent's identity.
| String, | ||
| nullable=True, | ||
| comment="Only when the agent is created from a template.", | ||
| max_length=20000, |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The max_length=20000 parameter is not valid for SQLAlchemy's mapped_column. SQLAlchemy String columns should use String(20000) to specify the length limit. The current code will create a column without a length constraint, which may cause issues when trying to insert strings longer than the database default.
| String, | |
| nullable=True, | |
| comment="Only when the agent is created from a template.", | |
| max_length=20000, | |
| String(20000), | |
| nullable=True, | |
| comment="Only when the agent is created from a template.", |
| from_template_id: Annotated[ | ||
| str | None, | ||
| PydanticField( | ||
| default=None, | ||
| description="Template identifier of the agent", | ||
| max_length=50, | ||
| ), | ||
| ] |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The field name mismatch between from_template_id in the Pydantic model and template_id in the SQLAlchemy table will cause the template_id to not be saved when creating agents. When model_dump() is called in the create() method, it will produce a dictionary with key from_template_id, but the AgentTable expects template_id. Consider either:
- Renaming the Pydantic field to
template_idto match the database column - Using Pydantic's
Field(alias="template_id")withby_alias=Truein model_dump - Manually mapping the field before passing to AgentTable
| # Get template_id from the agent | ||
| # Since Agent model may not have template_id mapped, we query from DB | ||
| async with get_session() as db: | ||
| result = await db.execute( | ||
| select(AgentTable.template_id).where(AgentTable.id == agent.id) | ||
| ) | ||
| row = result.first() | ||
| if row is None: | ||
| return agent | ||
| template_id = row[0] |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The render_agent function queries the database twice for the same agent - once to get the template_id and again in get_agent. This is inefficient. Consider passing the template_id as a parameter to render_agent or accepting the full AgentTable item to avoid the redundant database query at lines 71-77.
| ## v0.8.37 - 2025-01-27 | ||
|
|
||
| ### Features | ||
| - Frontend skill box display in chat interface | ||
| - Local frontend development improvements | ||
| - GPT image model updated to version 1.5 | ||
|
|
||
| ### Fixes | ||
| - Docker compose configuration fixes | ||
| - Debug authentication removed | ||
| - Various lint fixes | ||
|
|
||
| ### Chores | ||
| - Dependency updates | ||
|
|
||
| **Full Changelog**: https://github.com/crestalnetwork/intentkit/compare/v0.8.36...v0.8.37 |
Copilot
AI
Dec 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CHANGELOG entry appears to be unrelated to this PR. This PR is about refactoring agent template rendering, but the CHANGELOG describes frontend features, Docker fixes, and other unrelated changes. Either the CHANGELOG entry should be removed from this PR or it needs to be updated to reflect the actual changes made in this refactoring.
Changes
Migration Path
Template rendering logic moved from model layer to core layer:
All consuming code now uses from core layer, maintaining the same functionality with cleaner separation of concerns.
Related to template feature development.