# Non-Linear: AI Agent Integration ## Overview Non-Linear treats AI agents as first-class actors — not assistants bolted onto a human interface, but independent participants with their own accounts, roles, permissions, and graph navigation capabilities. ## Two Agent Modes ### Agent as User The agent operates independently within the project graph. It has its own account, picks up tasks, reports status, and navigates the decomposition tree autonomously. **Primary use case:** One-person team where an AI agent acts as a focused collaborator. **How the graph helps:** The decomposition tree gives the agent *rails*: - "What's the highest-priority unblocked leaf node in Backend?" → graph traversal query - "What's the status of the Auth component?" → read subtree, aggregate child statuses - "What should I work on next?" → find unblocked, assigned, in-progress leaves ### Agent as Assistant The agent helps human users by analyzing the graph and suggesting actions. **Primary use case:** Teams where AI augments human decision-making. **Examples:** - "Break this component into tasks" → agent suggests child nodes, human approves - "What's blocking the Auth epic?" → agent traverses subtree and lateral links - "Summarize progress on Dashboard this week" → agent reads subtree statuses and recent comments - "Suggest priority order for these tasks" → agent considers dependencies and blockers ## Agent API (v0.1) Governed by the same policy engine as human users. Agents authenticate with API tokens tied to their actor account. ### Layer Filtering All read endpoints accept an optional `layers` query parameter that controls which data layers are included in the response. This mirrors the UI layer toggles and lets agents scope their view to only the information they need. ``` ?layers=structure,work # Default: structure + issues (Layers 1+2) ?layers=structure,connections # Architecture view: structure + code dependencies (Layers 1+3) ?layers=structure,work,connections # Structure + issues + code dependencies (Layers 1+2+3) ?layers=all # All four layers ``` | Layer Value | Layer | What's Included | |-------------|-------|-----------------| | `structure` | 1 | Component nodes and component→component edges | | `work` | 2 | Issue nodes, work coordination links (blocks, duplicates, relates_to) | | `connections` | 3 | Code connection edges (depends_on, imports, calls_api, shares_db) | | `artifacts` | 4 | Artifact nodes and attachment edges | If `layers` is omitted, the default is `structure,work` (backward-compatible with the pre-layer API). The `structure` layer is always implicitly included — it cannot be excluded since it provides the base topology. ### Graph Traversal ``` GET /api/v1/nodes/{id} # Read single node GET /api/v1/nodes/{id}/children # Direct children GET /api/v1/nodes/{id}/subtree # Full subtree (depth-limited) GET /api/v1/nodes/{id}/parent # Parent node GET /api/v1/nodes/{id}/links # Outbound lateral links (filtered by active layers) GET /api/v1/nodes/{id}/backlinks # Inbound lateral links (filtered by active layers) GET /api/v1/nodes/{id}/path # Path from root to this node GET /api/v1/nodes/{id}/history # Change history timeline GET /api/v1/nodes/{id}/artifacts # Attached artifacts (Layer 4) GET /api/v1/nodes/{id}/connections # Code connections for this component (Layer 3) GET /api/v1/projects/{id}/root # Project root node GET /api/v1/projects/{id}/inbox # Triage inbox (rootless nodes) ``` ### Queries ``` GET /api/v1/projects/{id}/nodes?status=in_progress&assignee=agent-123 GET /api/v1/projects/{id}/nodes?label=bug&status=backlog GET /api/v1/projects/{id}/nodes?unblocked=true&status=todo GET /api/v1/projects/{id}/nodes?cycle=current GET /api/v1/projects/{id}/nodes?layers=structure,connections&type=component ``` ### Write Actions (v0.1) ``` POST /api/v1/nodes/{id}/comments # Add comment PATCH /api/v1/nodes/{id}/status # Change status PATCH /api/v1/nodes/{id}/parent # Triage: assign parent to inbox item ``` ### Write Actions (v0.1 — Layer 4) ``` POST /api/v1/nodes/{id}/artifacts # Attach an artifact (link or file) DELETE /api/v1/nodes/{id}/artifacts/{aid} # Remove an artifact ``` ### Deferred Actions (v0.2+) ``` POST /api/v1/nodes/{id}/children # Create child node POST /api/v1/nodes/{id}/links # Create lateral link (Layer 2 or Layer 3) DELETE /api/v1/nodes/{id}/links/{link_id} # Remove lateral link PATCH /api/v1/nodes/{id} # Edit node details POST /api/v1/nodes/{id}/connections # Declare a code connection (Layer 3, manual) ``` ### Authentication - Agents authenticate via API tokens (bearer tokens) - Each token is tied to an actor (agent account) - The actor has roles/policies assigned via the policy engine - Token scoping: a token can optionally be restricted to a subset of the agent's permissions ### Pagination All list endpoints use **cursor-based pagination**. Responses include a cursor for the next page and a flag indicating whether more results exist. **Response envelope:** ```json { "items": [ ... ], "next_cursor": "eyJpZCI6IjEyMyIsInRzIjoiMjAyNS0wMS0wMVQwMDowMDowMFoifQ==", "has_more": true } ``` **Query parameters:** | Parameter | Default | Max | Description | |-----------|---------|-----|-------------| | `limit` | 50 | 200 | Items per page | | `cursor` | null | — | Opaque cursor from previous response | | `max_depth` | 3 | 10 | Subtree query depth limit (subtree endpoint only) | - **Subtree queries** (`GET /nodes/{id}/subtree`) accept `max_depth` to cap traversal depth. The graph visualization uses this to load progressively — fetch immediate children on expand, not the entire tree at once. - **Children queries** (`GET /nodes/{id}/children`) are paginated but not depth-limited (they return a single level). - **Search/filter queries** (`GET /projects/{id}/nodes?...`) are always paginated. - Cursor encoding is opaque to the client. Internally it encodes the sort key (e.g., `created_at` + `id`) for stable pagination under concurrent writes. ### Response Format All responses include effective permissions on the returned resource. Links and backlinks are grouped by layer when multiple layers are requested. ```json { "node": { "id": "uuid-123", "short_id": "NL-42", "title": "Login component", "status": "in_progress", "labels": ["frontend", "p1"], "parent_id": "uuid-456", "children_count": 3, "active_layers": ["structure", "work", "connections"], "backlinks": { "work": { "blocked_by_count": 1, "relates_to_count": 2 }, "connections": { "depended_on_by_count": 3 } }, "links": { "work": [ { "type": "blocked_by", "target_id": "uuid-789", "target_accessible": true, "target_title": "SSO integration" } ], "connections": [ { "type": "imports", "target_id": "uuid-lib", "target_accessible": true, "target_title": "jwt-lib", "source": "inferred" } ] }, "artifacts_count": 2 }, "permissions": { "can_edit": false, "can_change_status": true, "can_comment": true, "can_create_child": false, "can_attach_artifact": true } } ``` When `layers` excludes a layer, the corresponding key is omitted from `links` and `backlinks`. The `artifacts_count` field is only present when `layers` includes `artifacts`. ``` ## Agent Design Patterns ### Focused Worker Agent ``` Loop: 1. Query subtree for unblocked, assigned, todo items 2. Pick highest priority 3. Change status to in_progress 4. Do work (external to tracker) 5. Post comment with results 6. Change status to done or in_review ``` ### Triage Agent ``` Loop: 1. Query inbox for unplaced nodes 2. For each, analyze title/description and match to existing subtrees 3. Assign parent (place in tree) 4. Post comment with rationale ``` ### Impact Analysis Agent ``` Uses layers: structure + connections (Layer 1 + Layer 3) 1. Query component with ?layers=structure,connections 2. Traverse DEPENDS_ON / IMPORTS / CALLS_API edges outward 3. Build a blast radius: "changing auth-service affects 4 downstream components" 4. Post comment with dependency diagram 5. Optionally cross-reference with Layer 2 (work): "3 in-progress issues touch affected components" ``` ### Decomposition Agent (v0.2+) ``` Triggered when: a node has label "needs-decomposition" 1. Read node context (parent, siblings, description) 2. Propose child nodes via comment or plan-then-apply 3. Human reviews and approves 4. Agent creates children ``` ## Webhooks (v0.1) Webhooks follow a **GitLab-style hooks model** — per-project registration with event filtering, signed payloads, and automatic retry. ### Registration Webhooks are registered per project via the API or settings UI: ``` POST /api/v1/projects/{id}/webhooks ``` ```json { "url": "https://agent.example.com/hooks/nonlinear", "secret": "whsec_...", "events": ["node.status_changed", "node.comment_added"], "active": true } ``` | Field | Type | Description | |-------|------|-------------| | `url` | string | HTTPS endpoint to receive POST requests | | `secret` | string | Shared secret for HMAC-SHA256 signature | | `events` | string[] | Event types to subscribe to (empty = all) | | `active` | bool | Enable/disable without deleting | ### Event Catalog | Event | Layer | Trigger | |-------|-------|---------| | `node.created` | 1/2 | New node (component or issue) created | | `node.status_changed` | 2 | Issue status transition | | `node.comment_added` | 2 | Comment posted on a node | | `node.link_created` | 2/3 | Lateral link created (work or code connection) | | `node.link_removed` | 2/3 | Lateral link removed | | `node.reparented` | 1/2 | Node moved to a different parent | | `node.cycle_added` | 2 | Issue added to a cycle | | `node.deleted` | 1/2 | Node (and subtree) deleted | | `artifact.attached` | 4 | Artifact attached to a node | | `artifact.removed` | 4 | Artifact removed from a node | | `connection.inferred` | 3 | Code connection auto-detected from repo analysis | | `repo.commit_associated` | 1 | Commit auto-associated with a component | Webhook subscriptions can filter by layer: `"events": ["layer:3"]` subscribes to all Layer 3 events only. ### Payload Format All webhook payloads share a common envelope: ```json { "event": "node.status_changed", "timestamp": "2025-06-15T14:30:00Z", "project_id": "uuid-project", "actor": { "id": "uuid-actor", "type": "user", "name": "alice" }, "data": { "node_id": "uuid-123", "short_id": "NL-42", "previous_status": "in_progress", "new_status": "in_review" } } ``` The `data` field varies by event type. Each event includes the affected node's `node_id` and `short_id` at minimum. ### Signature Verification Every webhook request includes an `X-NonLinear-Signature` header containing an HMAC-SHA256 hex digest of the raw request body, computed with the webhook's shared secret: ``` X-NonLinear-Signature: sha256=a1b2c3d4e5f6... ``` Receivers should verify the signature before processing to confirm authenticity. ### Delivery & Retry - Webhooks are delivered asynchronously via the Taskiq worker. - **Timeout:** 10 seconds per delivery attempt. - **Retry:** 3 attempts with exponential backoff (10s, 60s, 300s). - **Failure handling:** After 3 failed attempts, the event is logged and dropped. After 50 consecutive failures across any events, the webhook is automatically deactivated and the project owner is notified. - **Ordering:** Best-effort chronological. Not guaranteed under high concurrency. ## MCP Compatibility (v0.2+) Expose the Non-Linear API as an MCP server so AI agents built on LLM frameworks can connect natively.