api-research-task-resources.md 7.6 KB

Research Task API Contract

Status: active mainline contract
Scope: research task collection, task detail, task-scoped analysis/crawler/report resources, and compatibility with legacy task routes.


1. Purpose

/api/research-tasks is the resource-oriented entry for the research-task main workflow.

This path is intended to become the frontend's default task API surface:

  • research task collection and active task snapshot
  • list-oriented task view summaries for task center style pages
  • task detail
  • activate task
  • task-scoped analysis resource
  • task-scoped crawler resource
  • task-scoped report resource

The legacy /api/research/tasks/... routes remain available as compatibility aliases during migration.


2. Shared Conventions

2.1 Response envelope

All documented routes return a JSON object with a top-level success field.

Typical success shape:

{
  "success": true
}

Typical not-found shape:

{
  "success": false,
  "message": "Research task not found."
}

2.2 Research task identifiers

  • Canonical task identifier field in route params: task_id
  • Response payloads generally expose both:
    • resource-style id
    • compatibility field task_id

2.3 Linked sub-resources

Task-scoped child resources are read conservatively:

  • /crawler only exposes the crawler job linked by crawler_job_id
  • /analysis* uses analysis_run_id when available, otherwise falls back to the latest persisted analysis run where the current service explicitly supports it
  • /report only exposes the report job linked by report_job_id

The task-scoped endpoints do not fall back to unrelated global runtime jobs.


3. Collection And Detail

3.1 GET /api/research-tasks

Returns the current research-task snapshot.

Response fields:

  • active_task: current active task or null
  • tasks: recent task list

Example:

{
  "success": true,
  "active_task": {
    "id": "venue-20260420101010-ab12cd",
    "task_id": "venue-20260420101010-ab12cd",
    "title": "Alias Venue",
    "status": "draft",
    "generated_query": "..."
  },
  "tasks": [
    {
      "id": "venue-20260420101010-ab12cd",
      "task_id": "venue-20260420101010-ab12cd",
      "title": "Alias Venue",
      "status": "draft"
    }
  ]
}

3.2 POST /api/research-tasks

Creates or updates a research task.

Common request fields:

  • venue_name
  • city
  • research_focus
  • venue_type
  • time_range
  • benchmark_venues
  • notes

Response fields:

  • task: saved task
  • active_task: current active task after save
  • tasks: recent task list after save

3.3 GET /api/research-tasks/task-views

Returns a list-oriented summary payload for pages that need task-centered list cards without activating each task first.

Response fields:

  • active_task_id: current active task id or null
  • task_views: list of task view entries

Each task_views[] item includes:

  • task_id
  • task
  • crawler
  • report

Notes:

  • task reuses the standard research task response item
  • crawler reuses the task-scoped crawler resource payload shape
  • report reuses the task-scoped report resource payload shape
  • the route is intentionally list-oriented and read-only; it does not activate or mutate tasks

3.4 GET /api/research-tasks/{id}

Returns a single research task resource.

Response fields:

  • task

3.5 POST /api/research-tasks/{id}/activate

Switches the active research task.

Response fields:

  • active_task
  • tasks

4. Task-Scoped Analysis Resources

4.1 GET /api/research-tasks/{id}/analysis-run

Returns the latest analysis-run snapshot for the task.

Response fields:

  • task_id
  • analysis_run_id
  • analysis_run

Minimal example:

{
  "success": true,
  "task_id": "task-1",
  "analysis_run_id": null,
  "analysis_run": null
}

4.2 GET /api/research-tasks/{id}/analysis-runs

Returns persisted analysis-run history for the task.

Response fields:

  • task_id
  • analysis_run_id
  • analysis_runs

4.3 GET /api/research-tasks/{id}/analysis

Returns the task-scoped analysis resource view.

Response fields:

  • task_id
  • analysis

Typical analysis payload includes:

  • status
  • summary
  • history
  • stats
  • current_run

4.4 Related write path

The write-side trigger for analysis is still:

  • POST /api/search

When called with research_task_id, the application layer resolves the task query and starts analysis dispatch for that task.


5. Task-Scoped Crawler Resource

5.1 GET /api/research-tasks/{id}/crawler

Returns the task-scoped crawler resource.

Response fields:

  • task_id
  • crawler

Typical crawler payload includes:

  • crawler_job_id
  • status
  • task_status
  • current_job
  • jobs
  • summary
  • history

Notes:

  • If the task has no linked crawler job, the endpoint still returns a valid resource payload with linked fields empty.
  • The resource does not borrow the global current crawler job from another task.

5.2 Related write paths

Crawler writes still live under the crawler API:

  • POST /api/crawler/start
  • POST /api/crawler/stop

When the frontend starts crawler work for a task, it should include research_task_id so that crawler_job_id can be synced back to the task.


6. Task-Scoped Report Resource

6.1 GET /api/research-tasks/{id}/report

Returns the task-scoped report resource.

Response fields:

  • task_id
  • report

Typical report payload includes:

  • report_job_id
  • status
  • task_status
  • current_job
  • jobs
  • summary
  • history

Notes:

  • If the task has no linked report job, the endpoint returns an empty-but-valid task-scoped resource.
  • The resource does not fall back to the latest unrelated global report task.

6.2 Related write path

The write-side trigger for report generation is still:

  • POST /api/report/generate

To keep the task workflow linked, callers should pass research_task_id.

That allows the backend to sync report_job_id back to the research task and expose the same job through /api/research-tasks/{id}/report.


7. Compatibility Mapping

The following legacy routes remain supported and currently delegate to the same application-layer payload builders:

Resource-oriented path Legacy compatibility path
GET /api/research-tasks GET /api/research/tasks
POST /api/research-tasks POST /api/research/tasks
GET /api/research-tasks/task-views no legacy alias
GET /api/research-tasks/{id} no exact legacy detail route
POST /api/research-tasks/{id}/activate POST /api/research/tasks/{id}/activate
GET /api/research-tasks/{id}/analysis-run GET /api/research/tasks/{id}/analysis-run
GET /api/research-tasks/{id}/analysis-runs GET /api/research/tasks/{id}/analysis-runs
GET /api/research-tasks/{id}/analysis GET /api/research/tasks/{id}/analysis
GET /api/research-tasks/{id}/crawler GET /api/research/tasks/{id}/crawler
GET /api/research-tasks/{id}/report GET /api/research/tasks/{id}/report

Migration guidance:

  • New frontend code should prefer /api/research-tasks/...
  • Existing callers may continue using /api/research/tasks/... during migration
  • New task-centric documentation should treat /api/research-tasks/... as the primary path

8. Verification References

The following tests currently lock this contract:

  • tests/integration/test_web_api_smoke.py
  • tests/integration/test_web_api_factory_smoke.py
  • tests/unit/backend/test_crawler_routes.py
  • tests/unit/application/test_analysis_service.py
  • tests/unit/application/test_report_query_service.py
  • tests/unit/application/test_report_service.py