non-linear-docs/05-AGENT-INTEGRATION.md

8.7 KiB

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.

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
GET /api/v1/nodes/{id}/backlinks          # Inbound lateral links
GET /api/v1/nodes/{id}/path              # Path from root to this node
GET /api/v1/nodes/{id}/history            # Change history timeline
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

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

Deferred Actions (v0.2+)

POST   /api/v1/nodes/{id}/children        # Create child node
POST   /api/v1/nodes/{id}/links           # Create lateral link
DELETE /api/v1/nodes/{id}/links/{link_id} # Remove lateral link
PATCH  /api/v1/nodes/{id}                 # Edit node details

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:

{
  "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:

{
  "node": {
    "id": "uuid-123",
    "short_id": "NL-42",
    "title": "Login component",
    "status": "in_progress",
    "labels": ["frontend", "p1"],
    "parent_id": "uuid-456",
    "children_count": 3,
    "backlinks": {
      "blocked_by_count": 1,
      "relates_to_count": 2
    },
    "links": [
      {
        "type": "blocked_by",
        "target_id": "uuid-789",
        "target_accessible": true,
        "target_title": "SSO integration"
      },
      {
        "type": "relates_to",
        "target_id": "uuid-000",
        "target_accessible": false,
        "target_title": null
      }
    ]
  },
  "permissions": {
    "can_edit": false,
    "can_change_status": true,
    "can_comment": true,
    "can_create_child": false
  }
}

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

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
{
  "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 Trigger
node.created New node (component or issue) created
node.status_changed Issue status transition
node.comment_added Comment posted on a node
node.link_created Lateral link created
node.link_removed Lateral link removed
node.reparented Node moved to a different parent
node.cycle_added Issue added to a cycle
node.deleted Node (and subtree) deleted
repo.commit_associated Commit auto-associated with a component

Payload Format

All webhook payloads share a common envelope:

{
  "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.