Atlassian GraphQL Gateway (AGG) Client¶
Overview¶
The atlassian/ directory implements a production-grade Atlassian GraphQL Gateway client for Jira and related Atlassian products.
Core principle: Schema-driven, not guess-driven.
Architecture¶
1. API Layer (Fast-moving, Generated)¶
Purpose: Represent Atlassian GraphQL schema as it exists today.
Locations:
- python/atlassian/graph/gen/
- python/atlassian/rest/gen/
- go/atlassian/graph/gen/
- go/atlassian/rest/gen/
Source: graphql/schema.introspection.json
Rules: - Never hand-edit generated files - Regeneration must be deterministic - Missing schema fields → generator failure
2. Transport & Client Layer (Stable, Defensive)¶
Purpose: Safely execute GraphQL operations.
Locations:
- python/atlassian/graph/client.py
- python/atlassian/rest/client.py
- go/atlassian/graph/client.go
- go/atlassian/rest/client.go
Responsibilities:
- Authentication
- Rate limiting
- Retries (429 only)
- Logging
- Strict vs non-strict error handling
- Beta headers (X-ExperimentalApi)
3. Canonical Analytics Layer (Slow-moving, Stable)¶
Purpose: Define data model for developer health metrics.
Source of truth: openapi/jira-developer-health.canonical.openapi.yaml
Characteristics: - API-agnostic - Versioned by this repo - Backward-compatible - Designed for analytics, not transport
Examples: - JiraUser - JiraProject - JiraIssue - JiraChangelogEvent - JiraWorklog
Rules: - Must NOT leak API shapes (edges, nodes, cursors) - IDs are strings - Timestamps are RFC3339 - Prefer optional fields over brittle requirements
4. Mapping Layer (Explicit, Validated)¶
Purpose: Convert API models → canonical analytics models.
Locations:
- python/atlassian/graph/mappers/
- python/atlassian/rest/mappers/
- go/atlassian/graph/mappers/
- go/atlassian/rest/mappers/
Rules: - Required canonical fields MUST be validated - Missing required data → explicit error - No implicit defaults for semantic fields - Positive conditionals preferred - No business logic — mapping only
Rate Limiting (Non-Negotiable)¶
Atlassian AGG uses cost-based rate limiting:
| Parameter | Value |
|---|---|
| Default budget | 10,000 points/minute |
| Enforcement | HTTP 429 |
Retry-After format |
TIMESTAMP (not seconds) |
Required Behavior¶
Retry ONLY on HTTP 429
Compute wait = retry_after_timestamp - now
Cap wait using MaxWait
After MaxRetries429 → fail with RateLimitError
Do NOT retry 4xx (except 429)
Do NOT retry >= 500
Violating this will get your code reverted.
Pagination Rules¶
- Assume every connection paginates
- Support
pageInfo.hasNextPageandpageInfo.endCursor - Handle nested pagination (e.g., projects → opsgenie teams)
- Never assume single page
- Never hardcode page sizes
Authentication¶
Supported Modes¶
| Mode | Header | Use Case |
|---|---|---|
| OAuth Bearer | Authorization: Bearer <token> |
Primary |
| Basic Auth | Authorization: Basic <base64> |
Tenant gateway |
| Cookie Auth | Cookie: <value> |
Explicit opt-in |
Rules¶
- Auth MUST be injectable
- Never hardcode tokens
- Never log auth headers or cookies
- Tests MUST mock auth
Testing Contract¶
Unit Tests¶
Must mock HTTP and cover: - Pagination - Rate limiting (429) - Beta headers - Mapping validation - Error paths
Integration Tests¶
- Must be env-gated
- Skip cleanly if env vars missing
- Do NOT intentionally trigger rate limits
- Assert shape, not volume
Required Env Vars (Integration)¶
ATLASSIAN_GQL_BASE_URL- One of:
ATLASSIAN_OAUTH_ACCESS_TOKENATLASSIAN_EMAIL+ATLASSIAN_API_TOKENATLASSIAN_COOKIES_JSON
AI Agent Rules¶
If you are an AI agent:
| DO | DON'T |
|---|---|
| Fetch introspection | Invent GraphQL fields |
| Inspect schema | Assume schema stability |
| Generate models | Collapse API → analytics models |
| Map explicitly | Remove rate-limiting safeguards |
| Weaken error handling | |
| Introduce silent fallbacks |
If schema details are unclear:
- Fetch introspection
- Inspect schema
- Generate models
- Map explicitly
Guessing is a failure.
Schema Evolution¶
When Schema Changes¶
- Fetch new introspection
- Regenerate API models
- Update mappers if needed
- Update tests
- Verify canonical layer unchanged (or version bump if changed)
Canonical Layer Changes¶
- Require explicit versioning
- Maintain backward compatibility when possible
- Document breaking changes
- Update all downstream consumers
What This Repo Is NOT¶
- Not a thin demo client
- Not a static schema wrapper
- Not Jira-only
- Not tolerant of silent data corruption
Authority¶
If there is conflict between code comments, README, and AGENTS.md:
AGENTS.md wins.
If unsure: - Preserve correctness - Preserve explicitness - Preserve future schema evolution