**Phase 1 — Agent Usage Sync to AgentHub Collector**
- Add agent_usage service: per-agent stats (messages, tokens, conversations, unique users, first/last used)
- Collector sync now includes usage data in payload; sync_agent accepts optional db session
- Celery beat task runs every 6h to sync all active agents with fresh usage stats
**Phase 2 — LibreCodeInterpreter Integration**
- Add code-interpreter, redis, minio services to docker-compose.prod.yml
- CodeInterpreterTool (BaseTool): sandboxed execution via /exec, 13 languages, Python session persistence via conversation_id
- ToolContext extended with conversation_id and agent_slug
- enable_code_interpreter boolean on Agent model (migration 027), tool seeded in tool_definitions (migration 026)
- Code interpreter auto-injected into agent tools when enabled
- Frontend: CodeExecutionResult component with terminal-style stdout/stderr/files rendering
**Phase 3 — Agent API Endpoints**
- GET /api/v1/agents/{slug}/analytics — per-agent usage stats + daily time series
- POST /api/v1/agents/{slug}/execute — synchronous programmatic agent execution (non-SSE)
- Sub-routes registered before /{slug} to avoid FastAPI route conflict
**Phase 4 — Fix Department & Region RAG Scoping**
- Department filter now OR-includes global (null department) docs, matching region filter behaviour
- retriever.search_documents/retrieve_and_prepare/query accept department_ids/region_codes lists
- MatchAny used for multi-value Qdrant filters; chat.py passes full arrays from knowledge_scope
- Admin PATCH /users/{id} now validates region_code against the regions table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
66 lines
3.4 KiB
Python
66 lines
3.4 KiB
Python
"""
|
|
Agent model — configurable AI agents replacing hardcoded chat modes
|
|
"""
|
|
from sqlalchemy import Column, String, Boolean, DateTime, Float, Integer, Text, ForeignKey
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.orm import relationship
|
|
from app.database import Base
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
|
|
class Agent(Base):
|
|
"""
|
|
Configurable AI agent entity.
|
|
|
|
Replaces the hardcoded rag/assistant mode system.
|
|
System agents (is_system=True) are seeded from migration and cannot be
|
|
edited by anyone below super_admin.
|
|
"""
|
|
__tablename__ = "agents"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
slug = Column(String(50), unique=True, nullable=False, index=True) # url-safe: "rag", "hr-helper"
|
|
name = Column(String(100), nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
icon = Column(String(50), default="bot", nullable=False) # lucide icon name
|
|
color = Column(String(20), default="primary", nullable=False) # tailwind color token
|
|
category = Column(String(50), default="general", nullable=False) # "general", "hr", "finance", "it", "operations"
|
|
|
|
# LLM Configuration
|
|
llm_provider = Column(String(20), nullable=False) # "openai" | "anthropic" | "google"
|
|
llm_model = Column(String(100), nullable=False)
|
|
temperature = Column(Float, default=0.7, nullable=False)
|
|
max_tokens = Column(Integer, nullable=True) # optional output limit
|
|
|
|
# System prompt & UX
|
|
system_prompt = Column(Text, nullable=False)
|
|
welcome_message = Column(String(500), nullable=True) # greeting shown on empty chat
|
|
suggested_prompts = Column(JSONB, default=list, nullable=False, server_default='[]')
|
|
|
|
# Capabilities & Tools
|
|
tool_ids = Column(JSONB, default=list, nullable=False, server_default='[]') # ToolDefinition names
|
|
enable_rag = Column(Boolean, default=False, nullable=False)
|
|
knowledge_scope = Column(JSONB, default=dict, nullable=False, server_default='{}')
|
|
# knowledge_scope: {"department_ids": [], "region_codes": [], "all": false}
|
|
enable_file_upload = Column(Boolean, default=True, nullable=False)
|
|
enable_code_interpreter = Column(Boolean, default=False, nullable=False, server_default='false')
|
|
capabilities = Column(JSONB, default=list, nullable=False, server_default='[]') # extensible future caps
|
|
|
|
# Visibility & Access
|
|
visibility = Column(String(20), default="public", nullable=False) # "public" | "department" | "private"
|
|
allowed_department_ids = Column(JSONB, default=list, nullable=False, server_default='[]')
|
|
is_template = Column(Boolean, default=False, nullable=False) # appears in user catalog
|
|
|
|
# Ownership & Lifecycle
|
|
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
|
|
status = Column(String(20), default="draft", nullable=False) # "draft" | "active" | "archived"
|
|
is_system = Column(Boolean, default=False, nullable=False) # seeded system agents
|
|
|
|
# Timestamps
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
creator = relationship("User", foreign_keys=[created_by])
|
|
conversations = relationship("Conversation", back_populates="agent")
|