Task Tracking & Auto-generation

Phase 7 · 3 creation paths Team & Enterprise

Paid tier required

The Tasks API is available on Team and Enterprise plans only. Requests from a Starter team return HTTP 403.

Overview

xbrain tracks tasks as first-class objects alongside memory items and contacts. Tasks can be created in three ways: manually via the API or dashboard, automatically extracted from Granola meeting notes, or detected from chat messages by the task intent detector running in the LibreChat bridge.

Every task carries team_scope, project_scope, visibility, confidence, truth_level, source, and validation_status — the full 7-field tagging contract. This means tasks participate in the same scoped retrieval and truth-level promotion pipeline as the rest of the team's knowledge.

Three Creation Paths

Manual POST /v1/tasks · created_by = user ID

Any authenticated user creates a task directly via the API or the team dashboard. created_by is set to the user's ID. Assignee is validated to be a member of the same team — cross-team assignment returns 422.

Meeting extraction Granola ingest · created_by = NULL

When the Granola integration ingests a meeting note, Claude extracts action items and creates tasks automatically. These tasks have created_by = NULL, marking them as system-generated. They appear in the dashboard with a "from meeting" label.

Chat detection opt-in via TASK_INTENT_DETECTION=true

The LibreChat bridge monitors chat messages for action intent ("I'll handle the deployment tomorrow", "someone needs to review the contract"). When detected, it sets metadata.contains_action=true on the memory item, and memory-api's background hook _maybe_create_task_from_action creates the task with created_by = NULL. Disabled by default — enable via TASK_INTENT_DETECTION=true in your .env.

Task Fields

Field Type Description
id UUID Auto-generated primary key.
title string Task title. Required.
description string | null Optional longer description or context.
status enum todo (default), in_progress, done, cancelled.
team_scope string Team this task belongs to. Hard isolation.
project_scope string | null Sub-project within the team. null means team-wide.
assignee_id UUID | null User assigned to this task. Must be a member of the same team.
due_date date | null Optional due date in ISO 8601 format.
source string Origin: manual, granola:{note_id}, or chat:{message_id}.
created_by UUID | null NULL for system-generated tasks (meeting extraction, chat detection).
visibility enum team (default), project, or private.
confidence float 0.0–1.0. Set by the extraction pipeline.
truth_level enum Defaults to WORKING.
validation_status enum pending, approved, or rejected.

API Reference

List tasks

bashGET /v1/tasks

# All tasks for the team
curl "https://api.grooveos.app/v1/tasks" \
  -H "Authorization: Bearer $JWT" \
  -H "X-Team-Scope: excalibur"

# Filter by status
curl "https://api.grooveos.app/v1/tasks?status=todo&project_scope=fundraising" \
  -H "Authorization: Bearer $JWT" \
  -H "X-Team-Scope: excalibur"

# Poll for new tasks since a timestamp (ISO 8601)
curl "https://api.grooveos.app/v1/tasks?since=2026-05-07T12:00:00Z" \
  -H "Authorization: Bearer $JWT" \
  -H "X-Team-Scope: excalibur"

Query parameters

Parameter Type Description
status enum Filter by status: todo, in_progress, done, cancelled.
project_scope string Filter by project. Omit for all projects.
since ISO 8601 timestamp Return only tasks created or updated after this timestamp. Use for polling.
limit integer Max results (default 50, max 200).
offset integer Pagination offset.

Create a task

bashPOST /v1/tasks

curl -X POST "https://api.grooveos.app/v1/tasks" \
  -H "Authorization: Bearer $JWT" \
  -H "X-Team-Scope: excalibur" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Send pitch deck to investor",
    "description": "Use latest v3 deck from Drive",
    "status": "todo",
    "project_scope": "fundraising",
    "due_date": "2026-05-14",
    "visibility": "team",
    "confidence": 1.0,
    "truth_level": "WORKING",
    "validation_status": "pending"
  }'

Update task status

bashPATCH /v1/tasks/{task_id}

# Mark as done
curl -X PATCH "https://api.grooveos.app/v1/tasks/t1a2b3c4..." \
  -H "Authorization: Bearer $JWT" \
  -H "X-Team-Scope: excalibur" \
  -H "Content-Type: application/json" \
  -d '{"status": "done"}'

# Status changes generate a differentiated audit entry:
# task.status_changed { from: "todo", to: "done" }

Team Dashboard

The built-in task dashboard is accessible at /tasks in the projects-dashboard service (same port as the project board). It polls the Tasks API every 30 seconds, displays tasks grouped by status, and lets team members mark tasks as in-progress or done without touching the API directly.

The dashboard filters tasks by the team scope associated with the logged-in user's JWT — no configuration required.

Chat-based Task Detection

The LibreChat bridge includes a task_intent_detector that analyses outgoing chat messages for action intent. When a message contains a commitment or action item, the bridge sets metadata.contains_action=true on the stored memory item.

memory-api's _maybe_create_task_from_action background hook then reads this flag and creates a task with the message content as title, created_by = NULL, and source = "chat:{message_id}".

Opt-in with a kill-switch

Chat detection is disabled by default to avoid unintended task noise. Enable it per deployment with TASK_INTENT_DETECTION=true. Set it back to false to disable immediately — no restart required.

env — .env# Enable task detection from LibreChat chat messages
TASK_INTENT_DETECTION=true

# Model used for intent detection (defaults to claude-haiku for low latency)
ANTHROPIC_TASK_INTENT_MODEL=claude-haiku-4-5-20251001