Guides

Turn GitHub Issues into a work queue your agents drain

GitHub Issues is where your team files work. It is not a dispatcher. There is no atomic claim, so two agents grab the same ticket, no lease, so a dead agent’s work just strands, and no dependency-aware pull, so a blocked ticket still surfaces. Connect the repo to Retasc and every issue syncs in as a claimable queue item your agents pull from, then closes back on GitHub when the work ships.

· 7 min read

What a queue adds to GitHub Issues

Two agents can read GitHub Issues in the same second and both start #142, because the list has no atomic claim. Assigning an issue adds a label without a lock and still leaves a person deciding who does what. There is also no lease to reclaim work when an agent dies mid-issue, so the work stops without a signal or a handoff. GitHub Issues gives humans a place to report, discuss, and triage, but it does not walk the dependency graph when agents pick work, so an issue blocked on another can still be picked next.

Connect the repo and keep GitHub Issues as the reporting surface your team already uses. Each issue arrives in Retasc as a queue item with atomic claims, leases, and dispatch that respects dependencies, then waits for your sign-off. Once approved, agents pull separate issues from the queue, and completed work closes the source issue on GitHub when the connector has a token.

Connect a repo from the Dash

An org owner or admin connects each repo once in the Dash. The connector can use a raw GitHub token, so setup stays out of agent tools and model context, with a human entering the connection details. You provide the project for synced issues, the repo in owner/name form, and an optional GitHub token with issues:write to close source issues when work is done. Leave the token blank for a one-way feed, as described below.

Retasc generates an unguessable webhook URL server-side in the form https://<deployment>.convex.site/webhooks/github/<intakeId>, along with a signing secret shown exactly once. Copy the secret when it appears, because you cannot view it again. If you lose it, disconnect and reconnect the repo to generate a fresh one.

1. In the GitHub repo, open Settings, then Webhooks, then Add webhook, following the instructions in the Dash. 2. Paste the Payload URL, set Content type to application/json, and paste the Secret. 3. Choose "Let me select individual events" and check Issues. 4. Save the webhook to trigger GitHub’s immediate ping, which a healthy connector answers.

How a GitHub issue reaches an agent

After verifying the signature on a GitHub issue event, Retasc copies the title and body into a native queue item, encrypted at rest under your org’s own key like other Retasc content. It arrives as todo with no explicit priority, Retasc’s lowest-priority bucket, to avoid jumping the queue, plus a support label that lets you filter intake separately from native work. The issue waits for your sign-off in the Dash or through retasc triage before any agent can pull it. A GitHub milestone with a due date maps to the issue’s dueAt, feeding the deadline into Retasc’s dispatch, and every synced issue keeps a link back to its source.

GitHub webhook redeliveries are safe, and edits upstream do not create duplicate work in your queue. An event GitHub retries is a no-op because Retasc deduplicates on GitHub’s delivery id, while an upstream edit updates the same queue item through an upsert on its source id (github:owner/repo#n). Inbound sync refreshes content without changing the issue’s Retasc status, leaving your agents in control of its lifecycle. That separation prevents inbound updates and outbound closes from triggering each other in a loop.

When Retasc closes the GitHub issue

With a GitHub token on the connector, an agent marking a synced issue done in Retasc triggers a PATCH to the GitHub API that closes the source issue as completed. Marking it canceled closes the GitHub issue as not planned. The person who filed the ticket sees it resolve in the same place they reported it. You do not need to switch tabs to make the corresponding change in GitHub.

The close is best-effort and runs only on a real transition into done or canceled. Retasc schedules it after committing its own status change, so a GitHub outage or stale token leaves the source issue open and logs the failure without rolling back the work. You can see that failure in the log. Closing an issue on GitHub does not change its Retasc status, because the queue controls the lifecycle once the issue has synced in.

What changes when you add a token

Without a token, the connector is a one-way feed: issues arrive in Retasc for agents to work, and nothing is written back to the source repo. This is the default for a repo you want to process without updating it. A token with issues:write makes the same connector close source issues, and you can add one later by reconnecting without changing how inbound sync works. GitLab uses the same approach on gitlab.com and self-hosted installations.

Every delivery is checked against an HMAC-SHA256 signature over the raw body before parsing, whether the connector has a token or runs as a one-way feed. An unknown or revoked connector returns the same 401 as a bad signature, so probing the webhook path cannot distinguish them. Connectors stay scoped to your org, with the signing secret and GitHub token stored server-side and never returned through the API or agent tools, which report only whether a token is present. Revoking a connector in the Dash stops sync immediately and preserves the issues already imported, so you can disconnect a company repo without removing its queued work.

Limits to check before connecting

A busy repo can bring both issues and pull requests into the queue. Check the scope and sync limits before connecting it.

Pull request sync is off by default so a busy repo does not fill the queue with review work before you choose to include it. To sync pull requests, turn on Sync-PRs on the connector and name a reviewer. A synced PR closes at the source only when its work is canceled. When the work is done, the PR stays open for a human to merge.

Common questions

Can AI agents work my GitHub Issues automatically?

Connect the repo in the Retasc Dash and each GitHub issue becomes a queue item, held for your sign-off before agents can pull it. Your agents use MCP to claim issues atomically and work each one on its own branch. With a token on the connector, completed work closes the source issue on GitHub. Your team keeps reporting issues in GitHub, while Retasc dispatches that work to the agents pulling from its queue.

Does closing a Retasc issue close the GitHub issue?

A connector with a GitHub token carrying issues:write closes the source issue as completed when you mark the synced issue done, or as not planned when you mark it canceled. Without a token, sync is one-way and writes nothing back. The close is best-effort because it runs after Retasc commits its own transition. A GitHub outage leaves the source issue open and logs the failure without rolling back that transition.

Is the GitHub sync one-way or two-way?

The connector supports both modes, with the token deciding which one you use. Without a token, issues flow into Retasc for agents to work, and nothing is written back. Add a token with issues:write to close source issues when the work is done. You can start one-way, then reconnect with a token later.

How is the GitHub webhook secured?

Retasc verifies every delivery with an HMAC-SHA256 signature over the raw request body, using a signing secret generated and stored server-side. An unknown or revoked connector returns the same 401 as a bad signature, preventing callers from enumerating webhook URLs through those responses. Each connector is scoped to your org. The signing secret and GitHub token are never returned through the API or agent tools.

Signup gives you $10 of usage, and connecting a repo takes a few minutes in the Dash. If you are bringing a backlog from another service, the Linear import puts those issues into the queue the same way, while the parallel agents guide covers how to run the fleet that works through them.

$ npx @retasc/cli@latest bind
Other ways Run the fleet that drains it