Imported from PostHog/posthog-foss (
products/autoresearch/backend/presentation/AGENTS.md). Install upstream withnpx skills add PostHog/posthog-foss --skill presentation. Copyright stays with the author.
API
The HTTP surface — and, because of how PostHog's codegen works, considerably more than that.
These serializers are the source of truth for three downstream artifacts: the REST API itself, the generated frontend TypeScript types, and the 29 autoresearch-* MCP tools that the sandbox agent uses to drive its own training run.
A vague help_text here becomes a vague tool description that a model has to guess at. Treat serializer annotations as agent-facing documentation, because they are.
This package lands one endpoint group at a time. Pipeline CRUD, the pre-create helpers, and the read-only model, run and training-run viewsets are here; the lifecycle actions, the training-run agent surface, and suggestions arrive in later pieces of the split tracked in #88464. The MCP tools arrive at the end of it.
What lives here
views/views.pyFour viewsets, registered in../routes.pyunderproject_autoresearch_*basenames and nested pipeline-first.AutoresearchPipelineViewSet— full CRUD plus the pre-create helperstemplates,resolve-template,validate.AutoresearchModelViewSet,AutoresearchRunViewSet,AutoresearchTrainingRunViewSet— read-only.
views/serializers.pyRequest and response shapes, plusresolve_target(), which turns a pipeline'starget_eventortarget_definition(an action reference) into the resolved target the rest of the product uses. It refuses the product's ownautoresearch_predictionevent, and an action with a step that can match it, because the labeler and online validation exclude that event from every scan.
Access control
Every viewset sets scope_object = "autoresearch" and splits scope_object_read_actions / scope_object_write_actions, so custom actions are classified explicitly rather than inheriting a default.
AutoresearchAccessPermission gates on the autoresearch feature flag via ../access.py.
A new @action must be added to one of those two lists. Omitting it is not a compile error and not a test failure — it is a permissions bug.
Where the rest of the system meets this package
- Routing —
../routes.py(register_routes), nested pipeline → models / runs / training_runs. - Frontend types — generated into
../../frontend/generated/via drf-spectacular + Orval. Never hand-edit those; change the serializer and regenerate withhogli build:openapi. - Calls into —
../dataset/(validate, templates,resolve_target).
Declare the response when it differs from the request
create validates with AutoresearchPipelineCreateSerializer but responds with AutoresearchPipelineSerializer. drf-spectacular infers responses from get_serializer_class(), so without an explicit responses= it documents the write shape as the response.
That broke the MCP build: autoresearch-create sets enrich_url: '{id}', the generated handler read result.id, and the declared type had no id. Now pinned with @extend_schema(responses={201: AutoresearchPipelineSerializer}).
Any action whose response shape differs from its request needs the same treatment — the mismatch is invisible in Python and only shows up as a TypeScript error two codegen steps downstream.
When editing this flow
- Annotate everything.
help_texton fields,@extend_schemaon custom actions. These flow straight into MCP tool schemas and generated types; an unannotated action produces an empty schema an agent cannot use. - Classify every new
@actionintoscope_object_read_actionsorscope_object_write_actions. - Regenerate after serializer changes (
hogli build:openapi) and commit the generated files — CI checks for drift. - If you add an endpoint, update this file to match.