Expose research planning information

This commit is contained in:
faligam
2026-09-07 12:17:38 +02:00
parent 5f237d535f
commit 2c532bc9bb
4 changed files with 118 additions and 1 deletions

View File

@@ -235,6 +235,14 @@ class ReportResponse(BaseModel):
generated_at: str = ""
class PlanResponse(BaseModel):
"""GET /v1/research/{id}/plan — validated planner output for a run."""
research_id: str
plan: dict[str, Any] | None = None
available: bool = False
class ErrorResponse(BaseModel):
"""Fehlerantwort."""
@@ -397,6 +405,12 @@ async def _run_pipeline(run: _ResearchRunState, request: ResearchRequest, budget
research_id = run.research_id
stage_ctx = {"research_run_id": research_id}
def store_plan(plan: dict[str, Any]) -> None:
"""Make the validated plan available as soon as planning finishes."""
run.plan = plan
run.updated_at = _now()
_save_run(run)
logger.info(
"[pipeline] Starting background research: run_id=%s query='%s'",
research_id,
@@ -416,6 +430,7 @@ async def _run_pipeline(run: _ResearchRunState, request: ResearchRequest, budget
budget_config=budget,
depth=request.depth,
priority=Priority.NORMAL,
on_plan_created=store_plan,
)
stage_ctx["stage"] = "planning"
@@ -449,6 +464,10 @@ async def _run_pipeline(run: _ResearchRunState, request: ResearchRequest, budget
logger.info("[pipeline] run_id=%s stage=synthesizing", research_id)
result = await orchestrator.run()
# The plan is structured, validated output from the planner. Persist it
# independently from the final report so it remains inspectable even
# when a later pipeline step fails.
run.plan = result.get("plan")
if result.get("success"):
run.state = ResearchRunState.COMPLETED.value
@@ -629,6 +648,21 @@ async def get_evidence(research_id: str) -> EvidenceResponse:
)
@router.get(
"/v1/research/{research_id}/plan",
response_model=PlanResponse,
summary="Get the validated research plan for a research run",
)
async def get_plan(research_id: str) -> PlanResponse:
"""Return the planner's structured strategy, never its prompt or raw output."""
run = _load_run(research_id)
return PlanResponse(
research_id=run.research_id,
plan=run.plan,
available=run.plan is not None,
)
@router.get(
"/v1/research/{research_id}/report",
response_model=ReportResponse,