Redesign Python AI engine (#5991)

# Description of Changes
Redesign the Python AI engine to be properly agentic and make use of
`pydantic-ai` instead of `langchain` for correctness and ergonomics.
This should be a good foundation for us to build our AI engine on going
forwards.
This commit is contained in:
James Brunton
2026-03-26 10:35:47 +00:00
committed by GitHub
parent 9500acd69f
commit e10c5f6283
211 changed files with 3891 additions and 27744 deletions
@@ -0,0 +1,13 @@
from .agent_drafts import router as agent_draft_router
from .execution import router as execution_router
from .orchestrator import router as orchestrator_router
from .pdf_edit import router as pdf_edit_router
from .pdf_questions import router as pdf_question_router
__all__ = [
"agent_draft_router",
"execution_router",
"orchestrator_router",
"pdf_edit_router",
"pdf_question_router",
]
@@ -0,0 +1,32 @@
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends
from stirling.agents import UserSpecAgent
from stirling.api.dependencies import get_user_spec_agent
from stirling.contracts import (
AgentDraftRequest,
AgentDraftWorkflowResponse,
AgentRevisionRequest,
AgentRevisionWorkflowResponse,
)
router = APIRouter(prefix="/api/v1/agents", tags=["agents"])
@router.post("/draft", response_model=AgentDraftWorkflowResponse)
async def draft_agent(
request: AgentDraftRequest,
agent: Annotated[UserSpecAgent, Depends(get_user_spec_agent)],
) -> AgentDraftWorkflowResponse:
return await agent.draft(request)
@router.post("/revise", response_model=AgentRevisionWorkflowResponse)
async def revise_agent(
request: AgentRevisionRequest,
agent: Annotated[UserSpecAgent, Depends(get_user_spec_agent)],
) -> AgentRevisionWorkflowResponse:
return await agent.revise(request)
@@ -0,0 +1,19 @@
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends
from stirling.agents import ExecutionPlanningAgent
from stirling.api.dependencies import get_execution_planning_agent
from stirling.contracts import AgentExecutionRequest, NextExecutionAction
router = APIRouter(prefix="/api/v1/agents", tags=["agents"])
@router.post("/next-action", response_model=NextExecutionAction)
async def next_action(
request: AgentExecutionRequest,
agent: Annotated[ExecutionPlanningAgent, Depends(get_execution_planning_agent)],
) -> NextExecutionAction:
return await agent.next_action(request)
@@ -0,0 +1,19 @@
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends
from stirling.agents import OrchestratorAgent
from stirling.api.dependencies import get_orchestrator_agent
from stirling.contracts import OrchestratorRequest, OrchestratorResponse
router = APIRouter(prefix="/api/v1/orchestrator", tags=["orchestrator"])
@router.post("", response_model=OrchestratorResponse)
async def orchestrate(
request: OrchestratorRequest,
agent: Annotated[OrchestratorAgent, Depends(get_orchestrator_agent)],
) -> OrchestratorResponse:
return await agent.handle(request)
@@ -0,0 +1,19 @@
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends
from stirling.agents import PdfEditAgent
from stirling.api.dependencies import get_pdf_edit_agent
from stirling.contracts import PdfEditRequest, PdfEditResponse
router = APIRouter(prefix="/api/v1/pdf/edit", tags=["pdf-edit"])
@router.post("", response_model=PdfEditResponse)
async def pdf_edit(
request: PdfEditRequest,
agent: Annotated[PdfEditAgent, Depends(get_pdf_edit_agent)],
) -> PdfEditResponse:
return await agent.handle(request)
@@ -0,0 +1,19 @@
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends
from stirling.agents import PdfQuestionAgent
from stirling.api.dependencies import get_pdf_question_agent
from stirling.contracts import PdfQuestionRequest, PdfQuestionResponse
router = APIRouter(prefix="/api/v1/pdf/questions", tags=["pdf-questions"])
@router.post("", response_model=PdfQuestionResponse)
async def pdf_questions(
request: PdfQuestionRequest,
agent: Annotated[PdfQuestionAgent, Depends(get_pdf_question_agent)],
) -> PdfQuestionResponse:
return await agent.handle(request)