GitHub Issue Import & Export
Two-way sync between GitHub issues and AACWorkflow — import existing backlog, sync fields, and export updates.
The GitHub Issue Import & Export feature lets teams bring their existing GitHub issues into AACWorkflow and keep them synchronized. This is essential for teams that already track work in GitHub Issues but want to adopt AACWorkflow's AI agents without losing their backlog.
Overview
This feature provides:
- One-shot import — pull open GitHub issues into AACWorkflow as a backlog load
- Back-link records — every imported issue has a reference back to its GitHub URL
- Two-way field sync — title, description, and status stay in sync on both sides
- Conflict resolution — when both sides change, apply a configurable strategy (last-writer-wins, AACWorkflow-wins, GitHub-wins)
- Pause/resume — stop syncing a specific issue without disconnecting the integration
Supported fields
| GitHub field | AACWorkflow field | Sync direction | Notes |
|---|---|---|---|
title | Issue title | Two-way | Kept in sync automatically |
body | Issue description | Two-way | Markdown format is compatible both ways |
state (open/closed) | Status | Two-way | Closed issues map to your workspace's "Done" status |
assignees[0] | Assignee | GitHub → AACWorkflow | Only if the GitHub login matches a workspace member |
labels | — | Not synced | Can be mapped in v2 |
html_url | Back-link | GitHub → AACWorkflow | Shown as a chip on the issue page |
Note: Only the first GitHub assignee is synced. Agent assignees in AACWorkflow are never exported to GitHub.
Import workflow
Step 1: Trigger import
Navigate to Settings → GitHub and click Import Issues. You'll see a form:
Import from: owner/repo
Filters:
- State:
open,closed, or both - Labels: optional filter (e.g.,
bug,feature) - Since: optional date filter
Click Import. AACWorkflow:
- Fetches matching issues from GitHub via the GitHub App token
- For each issue that doesn't already have a mapping, creates an AACWorkflow issue
- Records the mapping in the
external_issuetable - Returns
{ imported: 42, skipped: 0, mappings: [...] }
Import is idempotent. Running import twice on the same repo results in the same number of AACWorkflow issues (no duplicates).
Step 2: Review mappings
Go to Settings → GitHub → Issue Mappings. You'll see a table of all synced issues:
| AACWorkflow title | GitHub URL | Synced | Last sync | Status |
|---|---|---|---|---|
| Add OAuth to MCP | https://github.com/org/repo/issues/123 | enabled | 2 min ago | In Sync |
| Fix login bug | https://github.com/org/repo/issues/124 | enabled | 5 min ago | GitHub updated |
Click any row to:
- View the back-link to the GitHub issue
- Pause/resume sync for that issue
- Manually trigger a sync now
Two-way sync
Sync directions
GitHub → AACWorkflow (webhook): When a GitHub issue is edited, GitHub sends a webhook. AACWorkflow applies the changed fields (title, description, state) to the mapped AACWorkflow issue.
AACWorkflow → GitHub (worker): When an AACWorkflow issue is updated, a background worker debounces the change and PATCHes the GitHub issue.
Periodic reconcile: Every 30 minutes, AACWorkflow checks for issues that haven't synced recently (e.g., missed webhooks) and reconciles them.
Conflict resolution
If both GitHub and AACWorkflow changed since the last sync, the conflict is resolved using the workspace's sync strategy:
| Strategy | Behavior |
|---|---|
newest_wins (default) | The version with the newer timestamp wins, field-by-field |
github_wins | GitHub version always wins |
aac_wins | AACWorkflow version always wins |
Important: When a conflict is resolved, the losing value is not lost — it's recorded in an audit comment on the AACWorkflow issue:
Synced from GitHub: Title changed from "Add OAuth" to "Add OAuth 2.1"
(AACWorkflow version: "Add OAuth" was overwritten by GitHub at 2025-06-22 15:30 UTC)Example: Simultaneous edits
Scenario: You edit the title in AACWorkflow while a team member edits the same issue on GitHub.
- AACWorkflow title: "Fix login timeout" → "Fix auth timeout" (you changed it)
- GitHub title: "Fix login timeout" → "Fix login session bug" (team member changed it)
- Both changes arrive within the reconcile window
Resolution (assuming newest_wins):
- GitHub
updated_at: 2025-06-22 15:30:00 - AACWorkflow
updated_at: 2025-06-22 15:29:45 - Result: GitHub version wins → AACWorkflow title becomes "Fix login session bug"
- Audit trail: An audit comment records the conflict and what was overwritten
Pause / Resume sync
To stop syncing a specific issue (e.g., you're doing detailed work in AACWorkflow and don't want GitHub changes to interfere):
- Go to Settings → GitHub → Issue Mappings
- Click the issue row
- Toggle Sync enabled → OFF
Syncing is paused for that issue only. Other issues continue syncing normally.
To resume:
- Toggle Sync enabled → ON
- Click Sync now to reconcile immediately
Disconnect workflow
If you disconnect the GitHub App from your workspace:
- All
external_issuemappings are cascaded and deleted - AACWorkflow issues remain (they are not deleted)
- Back-links are removed from issue pages
- The historical audit trail is kept for compliance
If you reconnect later, you'll need to re-import to rebuild mappings.
API
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/workspaces/{ws}/github/issues/import | Trigger import for a repo |
GET | /api/workspaces/{ws}/github/issues/mappings | List current mappings |
POST | /api/issues/{id}/github/sync | Force manual sync for one issue |
PATCH | /api/issues/{id}/github/sync | Enable/disable sync for one issue |
Example: Import via API
curl -X POST https://aacworkflow.example.com/api/workspaces/my-ws/github/issues/import \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"repo_owner": "my-org",
"repo_name": "my-repo",
"filters": {
"state": "open",
"labels": ["bug"],
"since": "2025-01-01T00:00:00Z"
}
}'Returns:
{
"imported": 12,
"skipped": 0,
"mappings": [
{
"external_issue_id": "...",
"issue_id": "...",
"gh_issue_number": 123,
"html_url": "https://github.com/my-org/my-repo/issues/123",
"sync_enabled": true
}
]
}Security
Only workspace admins can trigger import or disconnect the GitHub App.
- All queries filter by
workspace_id— no cross-workspace data leakage - Webhook signatures are verified before processing
- Installation tokens are never exposed to the client
- Assignee sync only maps verified workspace members (never creates invites)
Non-goals (future versions)
The following are intentionally NOT supported in v1:
- Importing GitHub Projects (boards), milestones, or labels as first-class objects
- Real-time comment sync (separate spec:
github-pr-comments-sync.md) - Creating brand-new GitHub issues from AACWorkflow (export is limited to issues that were imported)
Troubleshooting
"Import failed: permission denied"
You likely don't have admin permissions in the workspace. Only workspace admins can trigger import.
"Some issues were skipped (synced 40, skipped 2)"
Skipped issues already have a mapping. Re-running import on the same repo is idempotent — previously imported issues are not re-created.
"Title changed but didn't sync to GitHub"
The sync worker runs every 30 seconds (debounced). If the change hasn't synced within 5 minutes:
- Go to Settings → GitHub → Issue Mappings
- Click the issue row
- Click Sync now to force an immediate reconcile
- Check the audit log for errors
"Conflict keeps happening with the same issue"
You might be editing the issue on both sides frequently. Consider:
- Setting sync strategy to
aac_winsto prioritize AACWorkflow - Pausing sync while doing bulk edits, then resuming
- Using only one side for edits while the integration stabilizes