Cat Factory
Home
Get Started
GitHub
Home
Get Started
GitHub
  • Start

    • Introduction
    • Core Concepts
    • Quick Start
    • Tutorial: Your First Task to a Merged Pull Request
  • Guides

    • Recipes

      • Cookbook
    • Plan the work

      • Design Your Board
      • Clarify Requirements
      • Author a Document
      • Plan an Initiative
    • Run pipelines

      • Choose and Edit a Pipeline
      • Run a Pipeline
      • Schedule Recurring Work
      • Review and Merge Pull Requests
      • Control Spend with Budgets
    • Connect

      • Connect a Repository
      • Connect Issue & Document Sources
      • Feed Design Context to Agents
      • Preview and Test a Frontend
    • Models & prompts

      • Connect a Model Provider
      • Apply Standards with Prompt Fragments
      • Run a Claude Skill as a Step
      • Compare Prompts and Models in the Sandbox
    • Collaborate

      • Invite and Manage Your Team
      • Share Services Across Workspaces
      • Register Foundational Services
  • Deploy

    • Run Locally
    • Deploy to Node.js
    • Deploy to Cloudflare
    • Deploy on Kubernetes
    • Lay Out a Kubernetes Cluster
    • Set Up a Local Kubernetes Cluster on Windows
    • Register the GitHub App
    • Set Up Enterprise SSO
    • Set Up Your Deployment Repository
    • Configuration
  • Operate

    • Observability
    • Set Up Notifications
    • Run Jobs on Your Own Runners
    • Provision Ephemeral Environments
    • Debug a Run from Outside the Browser
    • Troubleshooting
    • Upgrades & Data Retention
  • Extend

    • Add a Custom Agent Kind
    • Add a Custom Gate or Judge
    • Add a Custom Provider
    • Extend the App with Frontend Modules
    • Integration Manifests
    • Give Agents External Tools (MCP)
    • Package a Reusable Operation
    • Register an Initiative Preset
    • Public API
    • Official SDKs
    • MCP Server
    • Cloudflare OS Gatekeeper
  • Reference

    • Architecture
    • Agent Isolation Model
    • Security Model & Hardening
    • Packages & Repository Layout
    • GitHub and GitLab Support Matrix
    • Environment Variables
    • API Endpoint Reference
    • Glossary

Connect Issue & Document Sources

For teams whose requirements already live somewhere else, in a tracker ticket or a spec document. Cat Factory lets you link those sources directly to blocks, import them, and use them as agent context.

Supported sources

TypeSources
Issue trackersJira, GitHub Issues, Linear
DocumentsConfluence, Notion, GitHub repo docs, Linear Docs
Design contextFigma, Zeplin

GitHub repo docs lets you pull a Markdown/spec file straight from a connected repository (owner/repo:path, or a file URL), reusing the workspace's installed GitHub App.

Connect Linear per workspace under Integrations, either through OAuth (the "Connect" flow) or with a personal API key. It works across four capacities:

  • Document source: import Linear Docs as task context.
  • Task source: import Linear issues (with their sub-issues and relations, paginated) to link to a task or to seed a new board task.
  • Filing tracker: the tech-debt recurring pipeline and similar steps file new issues into a Linear team. Pick the team from a typeahead team picker in the tracker panel rather than pasting a team id.
  • Writeback: comment on the linked Linear issue when its PR opens, and transition the issue to a completed workflow state when the PR merges.

Design context (Figma and Zeplin)

Figma and Zeplin are design-context sources: Cat Factory pulls component structure, layout, and design tokens and renders them to Markdown so the UI coding agents get the design as context. They connect and link like any other document source, and everything specific to them (which credential, what the agent receives, the import caps, freshness) is on Feed Design Context to Agents.

Finding and linking context

The same inline context picker appears on the Add task popup and in the task inspector, so you attach material the same way whether the task is new or already exists. For a non-repo source (Confluence, Notion, Jira) you can:

  1. Search the source's catalogue by title or content (Confluence via CQL, Notion search, Jira via JQL, GitHub issues).
  2. Paste a page or issue URL (or id) directly.
  3. Pick something already imported into the workspace.

For a repo-backed source (GitHub, and GitLab through the same adapter) attaching a doc is a two-step pick: search for a repository, then choose one or more files, either by filtering on path or by browsing the repository tree (multi-select). A repo reachable only through your personal token is badged, since it resolves through the workspace's GitHub App at run time and can fail to link on a hosted deployment.

GitHub is available as a document source automatically once its App or PAT is installed, with no connect step. When no source is connected at all, the context section offers a Connect a source action that opens the connect flow over the task form and preserves what you've already typed, rather than a dead Attach button. Chosen items are imported and linked as agent context on create, with no separate import step. Search is scoped to the workspace's own integration installation, so you only ever see your own org's content.

Each attached document row shows its full URL on hover and opens in a new tab. If a link fails, the error names the specific cause (no access, rate-limited, not found) with a Copy details action, instead of a generic "could not be linked" message.

What a pasted link resolves to

A pasted reference is judged as you type, before anything is imported. The picker stages what the import will actually do, not the text you pasted, so a link that will not work is a correction you make while you are still writing the task.

  • The link is trimmed to its canonical form. Share links carry title segments and tracking parameters, and the chip shows the rebuilt link instead. For a few sources the id itself is the canonical form, because the URL cannot be rebuilt without knowing something the picker does not have (a Confluence site's base URL, a Linear workspace slug, which VCS host a repo doc lives on). Seeing an id rather than a URL is a normal answer there, not a failed resolution.
  • A reference that had to be widened says so. Some links name a part the source cannot address on its own, most often a Figma component instance. Rather than guess which frame you meant, the import widens to the whole file or project, and the picker states in an amber line exactly what was dropped, as you pasted it. "I attached this frame" and "I attached the entire design" would otherwise look identical.
  • A refusal names which correction it needs. Either no link of that shape will ever work for the selected source, in which case the message states the format that will, or the link is fine and points at a different source, in which case the picker names that source and offers to switch with your text unchanged.
  • An unreachable source is not a refusal. If the check cannot be made (an outage, a proxy error page), the reference stays stageable and the import remains the backstop it always was. A transient failure should not make a perfectly good link unattachable.
  • Attachments are fetched before the task exists. Anything you staged is resolved as part of creating the task, and one that could not be read is marked on the chip that caused it. Creation waits until you fix or remove it, rather than leaving you with a task that quietly lacks the spec it was written about.

Expand a document into board structure

An imported document can seed board structure instead of riding along as context. Cat Factory reads it, shows you a plan preview, and writes nothing until you approve. The question it answers depends on where you aim it:

  • At the board: what architecture does this document describe? The plan comes back as services, each with its modules and tasks. A large epic seeds a module with several task leaves, each carrying its slice of the document.
  • At an existing service: what work does this document imply inside a service that already exists? The plan comes back as modules and tasks for that service, and the modules it already has are taken into account, so the plan adds beside them rather than proposing a second "Checkout" next to the one that is there. The preview says which service it is planning into.

Approving creates exactly what the preview showed. A plan aimed at a service is authored for that service from the start, rather than a board-wide plan flattened into it, which is what keeps the approved preview and the created blocks the same thing.

A design document is always planned into a service, so the preview asks you to pick one. A design describes screens, and asked for an architecture a model will happily invent a service per Figma page. Aimed at a service it decomposes into one task per screen, state or flow, named after the frame it came from.

Planning normally uses the workspace's configured agent model. If no model is usable, or its answer cannot be read, it falls back to splitting the document by its own headings, so expanding always produces something. A deployment can force that deterministic split for everyone with the DOCUMENT_PLANNER setting.

Who can connect a source, and who can attach one

The two halves sit at different workspace roles, because they have different blast radius:

ActionRole
Search a source, paste a reference, import a page, attach it to a task, refresh it, expand it into structureMember. This is board authoring.
Connect or disconnect a sourceAdmin. It writes the workspace's stored credential for that source.
Tag a document as a kind's template or exemplarAdmin. It decides what every document run on the board writes from, not what one task reads.

The split is why the person who links the spec their task is about does not have to be the person who connected Confluence. It is also visible in the picker: a member sees the source named with no add a source entry, and the no-source empty state tells them to ask an admin, rather than offering a connect flow that would take a token and then refuse it. Viewers can read what is attached and attach nothing.

Creating a task straight from an issue

Beyond attaching an issue to a task you're already writing, you can turn an imported GitHub issue or Jira ticket into a brand-new board task in one step. There are two ways in:

  • A service frame header carries a Create task from issue button (shown when a tracker is offered). It opens the tracker-issue modal pinned to that service, with the issue search scoped to the service's linked GitHub repo, and the new task lands in that frame.
  • The task-source import modal lets you pick the service frame or module to create tasks in, then hit Create task on an issue.

You search the tracker by title to find a hit, no need to know the issue key. In a repo-scoped GitHub search, a pasted issue URL (or owner/repo#n shorthand) resolves to that exact issue and is offered first; a bare issue number resolves against the service's repo. Then:

  • A new leaf block is created (titled KEY: summary, its description seeded from the issue body) in the container you chose.
  • The issue is linked to the new task, so every agent step still sees the full issue (description, comments, and metadata) as context.

When the add-task form opens with a linked issue, it shows that issue's description read-only above your own editable field (labelled Additional notes). The issue body is folded into the saved description first, then your notes, so you add context without retyping the ticket.

The issue stays the source of truth: re-importing refreshes it. Creating a second task from an already-linked issue is refused, so one issue maps to one task rather than silently re-pointing. GitHub Issues and Jira both work this way on every runtime (Cloudflare, Node, and local); Linear is offered as a task source for import and linking too.

A headless integration does the same thing by naming the ticket on POST /api/v1/services/{serviceId}/tasks, which imports the issue and attaches it rather than flattening it into the description. A task dispatched this way has nobody in the app, so if it pins no risk policy it resolves the workspace's unattended default and can answer its own automatic checkpoints rather than waiting on a person. See Runs nobody is watching.

Bug hunt

Bug hunt is the interactive counterpart to the recurring bug-triage schedule: same board reading and same downstream pipeline, but you pick instead of the oldest match being claimed unattended.

Choose a connected tracker and one of its boards, and the open, unassigned bugs come back rated on impact against implementation complexity. Confirm one candidate and it is adopted as a bug task running the standard Triage & fix bug pipeline.

The issue-tracker panel

A workspace's tracker is configured in one place: Workspace settings → Issue tracker. It has three parts:

  • Filing tracker: where the tech-debt recurring pipeline and similar steps file new tickets, None, GitHub Issues, Jira (reveals a project-key field), or Linear (reveals a team picker).
  • Linking: per-source toggles for whether that tracker can be linked as task context. These are per-workspace and default on, so a workspace can use GitHub repos without offering their issues, or park a connected Jira.
  • Writeback: see below.

Each source has a Check setup button that runs a live diagnostic and reports a concrete status, ready, not_installed, not_connected, auth_failed, forbidden, or unreachable, so you can tell a missing GitHub App install from a bad Jira credential without starting a run to find out.

A context picker always shows which tracker it is searching, and offers to add one from there if the board has none.

GitHub issue search is repository-scoped

GitHub's issue search API carries no scope of its own, so an unqualified query returns whatever the credential can reach: under a personal token, that is every public repository on GitHub. Every issue search the platform makes therefore names its repository by construction, including the recurring bug-intake sweep, which imports its hit and starts a pipeline on it. Results are exactly the service's own issues. To link an issue from another repository, paste its URL; the by-reference row never rode the search path.

Push-driven intake

A tracker can push instead of being polled. Point the tracker's webhook at POST /webhooks/tasks/<source>/<workspaceId> and a qualifying issue event fires the matching intake schedule immediately rather than waiting for its interval.

The webhook removes the latency; it does not reorder the queue. Deduplication, the replace-link rule, and the pickup mark are the recurring schedule's, unchanged, and the schedule remains the sweep that catches missed deliveries. The HMAC signature is verified over the raw body before anything is parsed.

The same transport carries replies from the ticket. When a run posts its open questions onto the linked issue, someone can answer in the issue's own comments using an explicit grammar, never natural-language guessing:

CommentEffect
@cat-factory answer <id> <text>Answer the finding with that id.
@cat-factory dismiss <id>Dismiss the finding as not applicable.
@cat-factory proceedProceed with the requirements as they stand.
@cat-factory extra-roundRun one more review round.
@cat-factory stopStop the run.

Jira Cloud sends comment bodies as rich-text documents rather than plain strings; those are converted before the grammar reads them, so a formatted reply works like a plain one.

Registering a tracker from a deployment

The built-in sources (github, jira, linear) are not the whole vocabulary. A deployment can register its own task source on the TaskSourceRegistry under a namespaced id, <namespace>:<name>, the same shape custom task types use. Built-in ids stay bare, so nothing stored has to change.

A namespaced id is resolved against the registry at the boundary, so an unregistered one is refused by the thing that actually knows, while a bare non-built-in id still fails validation. That keeps a typo distinguishable from a registration. A registered source's board scope is carried as an opaque board id rather than being squeezed into one of the built-in vendors' fields.

A registered source is usable everywhere the built-ins are, including the public API's ticket input.

Writing back to the tracker

Cat Factory can keep the upstream issue updated as work progresses, so the tracker reflects reality without manual status-shuffling. Three workspace toggles under Issue tracker → Writeback control it:

  • Comment when a PR opens: posts a comment on the linked issue when the task's pull request opens.
  • Close as resolved when a PR merges: closes the issue when the PR merges (GitHub closes it natively; Jira transitions it to its first "Done" status; Linear transitions it to a completed workflow state).
  • Post open questions on a parked headless run: when a run started through the public API pauses to clarify requirements, posts its open questions on the linked issue, each with the id an answer names.

All three are on by default, and each can be overridden per task in the task inspector (Inherit workspace, On, or Off), so a one-off task can opt out of (or into) writeback without changing the workspace default.

Writeback only ever touches an issue a task is linked to, and nothing links one by accident: a link arrives when you import an issue, when the recurring intake picks one up, or when a headless caller files a task with a ticket. Each of those is a request to work the issue where it was filed, so the default closes the loop rather than leaving a merged pull request beside an issue still sitting open with nothing on it saying the work was done.

Writeback follows each linked issue's own source, not the filing tracker. A workspace with Filing tracker: None still comments on and closes the GitHub issue a task was filed from. The two settings are independent decisions.

The questions toggle exists because a headless caller has no in-app inbox to watch: the clarification reaches whoever filed the issue, and they can answer it over the API against the ids in the comment. It fires only for runs whose origin is the public API. A task started in the app is unaffected, and its clarification surface stays the in-app review window. The post is claimed once per review iteration and issue before it is attempted, so a retried or replayed run never double-posts onto an issue somebody is reading, and a tracker outage leaves the post retryable rather than lost.

A deployment driven entirely over the API can read and change the same three actions without opening the app: see Reading and setting tracker writeback.

Using sources as agent context

Once linked and imported, source content travels with the block:

  • The reviewer agent uses it to find gaps and risks.
  • The coder agent uses it to implement the task accurately.
  • Subsequent steps reference the same shared definition.

Container agents get the linked material in full: each step's prompt carries a short summary index, and the complete bodies are written into a git-excluded .cat-context/ directory in the workspace for the agent to read on demand.

A document that cannot actually reach the agent fails the run rather than being dropped quietly. A reference that resolves to a page with an empty body, and a corpus that overflows the materialized context budget, both used to leave the run looking healthy while the agent worked from a spec nobody noticed it never read. Both now refuse in the same words, naming what could not be delivered. Cat Factory also resolves references you name in a description, Jira keys, owner/repo#123, and URLs, against the imported corpus, so a task that mentions a ticket picks up that ticket's content even without an explicit link.

Enabling integrations

Document and issue integrations ship enabled; each workspace connects its own site and credentials in the UI (Confluence and Notion API access, Jira, and the GitHub-backed sources, which ride the workspace's GitHub App installation). Which task sources a workspace actually offers is then the per-workspace toggle described above. See Configuration → Document & task sources for the deployment-side knobs that remain.

Keep the source of truth where your team works

Linking beats copy-pasting: when the upstream ticket or doc is the canonical spec, importing keeps the agent's context aligned with what your team is actually tracking.


Next: keep agent costs predictable with Control Spend with Budgets.

Edit this page on GitHub
Last Updated: 8/12/26, 7:59 AM
Prev
Connect a Repository
Next
Feed Design Context to Agents