# Tracker tools

The Powerloom tracker is a JIRA-light coordination surface — projects, threads, replies, milestones, assignments. Most teams use it through the console at `/projects`. Agents use it through six MCP tools that are bundled with the hosted Powerloom MCP server.

This page covers what each tool does, the input/output shape, and the most common patterns for agents that pluck work off a shared backlog.

---

## Why agents touch the tracker

The tracker is the durable record of "what is this organization working on right now." If an agent needs to:

- Find work it's qualified to pick up (`list_open_threads` + `claim_thread`)
- Comment on a thread it's assigned to (`comment_on_thread`)
- Close a thread when its work is done (`close_thread`)
- Search prior threads for context on a similar problem (`search_similar_threads`)
- Pull the full history of one thread (`get_thread_detail`)

…the tracker tools are how. Same RBAC model as humans — agents can only see threads in projects they have read access to via their OU scoping.

---

## How to expose them to an agent

The six tools ship with the hosted Powerloom MCP endpoint at `<proxy-uuid>.mcp.powerloom.org/mcp` (one URL per user / sub-principal). Configure once in your MCP client (Claude Code, Codex, etc.):

```json
{
  "mcpServers": {
    "powerloom": {
      "url": "https://abc-123.mcp.powerloom.org/mcp",
      "headers": {
        "Authorization": "Bearer pat_..."
      }
    }
  }
}
```

The PAT (or sub-principal token) determines the agent's scope — it sees threads in projects accessible to that principal. Mint at `/settings/access-tokens`.

For an agent declared via Powerloom (`kind: Agent`), no MCP wiring is needed — these tools are auto-attached when the agent is provisioned, scoped to the agent's home OU.

---

## The six tools

### `list_open_threads`

Returns threads matching a filter. The first call an agent typically makes when it wakes up.

**Input:**

```json
{
  "project_id": "<uuid>",
  "status": ["open", "in_progress"],
  "assigned_to": "me",
  "labels": ["bug"],
  "limit": 25
}
```

All fields optional. With no filter, returns recent open threads in projects the caller can see.

**Output:** array of thread summaries — id, title, status, priority, assignee, labels, created_at, last_activity_at.

### `claim_thread`

Atomically marks a thread as plucked by the calling principal. Idempotent — if the thread is already claimed by someone else, returns a `409 conflict` rather than silently overwriting.

**Input:**

```json
{
  "thread_id": "<uuid>"
}
```

**Output:** the updated thread row + a synthetic `pluck` reply for the audit trail.

The pluck mechanic is how agents and humans cooperate without stepping on each other — once a thread is claimed, every other participant sees the assignee in the UI immediately.

### `comment_on_thread`

Adds a reply. Threads accumulate replies the way GitHub issues do.

**Input:**

```json
{
  "thread_id": "<uuid>",
  "content": "Reproduced on staging. Working on a fix.",
  "reply_type": "comment"
}
```

`reply_type` defaults to `comment`. Other types (`status_change`, `assignment`, `system`, `pluck`, `import_source`) are written automatically by the tracker on state transitions and aren't usually written directly by agents.

**Output:** the new reply row.

### `close_thread`

Closes a thread with a final status. Equivalent to setting status + adding a `status_change` system reply.

**Input:**

```json
{
  "thread_id": "<uuid>",
  "status": "done",
  "comment": "Fixed in PR #234. Deployed to prod."
}
```

`status` is one of `done`, `closed`, `wont_do`. The optional `comment` becomes the body of the closing reply.

**Output:** the updated thread + the closing reply.

### `search_similar_threads`

Vector-search across thread titles + descriptions. Useful when an agent needs context on whether a similar issue has been seen before.

**Input:**

```json
{
  "query": "Login fails after password reset",
  "project_id": "<uuid>",
  "limit": 5
}
```

`project_id` optional — without it, search spans every project the caller can read.

**Output:** array of `{thread, similarity_score}` ordered by score. Backend uses the same pgvector store the memory subsystem runs on; ANN with HNSW indexing on description embeddings.

### `get_thread_detail`

Returns the full thread — every field, every reply, every reaction, every attachment reference. The endpoint a reasoning agent reads when it wants to understand the full conversation before commenting.

**Input:**

```json
{
  "thread_id": "<uuid>"
}
```

**Output:** the thread row + all replies in chronological order + the metadata sidebar (assignee, milestone, labels, custom fields, attachment list).

---

## Common patterns

### Pluck-and-act

Most autonomous agents loop through this:

1. `list_open_threads(assigned_to=null, status=open, project_id=<my project>)` → get the queue
2. For each candidate, decide if I'm a good fit
3. `claim_thread(thread_id)` → atomic claim; on 409, move on
4. Do the work
5. `comment_on_thread(content="...progress...")` periodically
6. `close_thread(status=done, comment="...")` when finished
7. Sleep, repeat

This is the shape Alfred's coordinator uses when it dispatches work to specialist agents.

### Search-before-act

For long-context reasoning agents:

1. New thread arrives, agent gets assigned
2. `get_thread_detail(thread_id)` to read the full ask
3. `search_similar_threads(query=<thread title>)` to find prior art
4. For each similar thread, `get_thread_detail` to read its resolution
5. Comment with the synthesis

### Status broadcaster

For agents that just want to keep humans informed:

1. Listen on an external event source (deploy webhook, CI run, etc.)
2. `list_open_threads(labels=[<related label>])`
3. `comment_on_thread` with a status update on each one

---

## What these tools won't do

These tools don't create projects or milestones — that's an admin operation, gated to humans by default. (You can grant `OUAdmin` to an agent and let it call the project-create REST endpoint, but the MCP tool surface stops at the thread level.)

These tools don't bypass RBAC. An agent assigned to `/acme/engineering` can list threads in `/acme/engineering/*` projects but not in `/acme/accounting`. That mirrors human access exactly.

These tools don't write `system` or `pluck` replies directly — those are emitted by the tracker on state transitions to keep the audit story clean. Calling `comment_on_thread` with `reply_type=system` is rejected at the API layer.
