| title | GitHub primitive |
|---|---|
| description | Workflow-specific primitive: a typed GitHub integration step. Runs through the local `gh` CLI or a cloud proxy. |
The GitHub primitive is a workflow-specific primitive — an integration step shaped for workflow(). It gives a workflow a typed GitHub surface (create issues, open PRs, read files, merge branches) with one call site that works the same locally via gh or in cloud via Nango / relay-cloud.
It's bundled with the SDK — no separate install. If you've run npm install @agent-relay/sdk, you already have it.
Import createGitHubStep from the SDK's /github subpath and drop it in anywhere you'd use a regular .step():
import { workflow } from '@agent-relay/sdk/workflows';
import { createGitHubStep } from '@agent-relay/sdk/github';
await workflow('ship-readme')
.agent('writer', { cli: 'claude' })
.step('read-readme', createGitHubStep({
action: 'readFile',
repo: 'AgentWorkforce/relay',
params: { path: 'README.md' },
output: { mode: 'data', format: 'text' },
}))
.step('edit', {
agent: 'writer',
dependsOn: ['read-readme'],
task: `Current README:\n{{steps.read-readme.output}}\n\nClean up the intro.`,
})
.step('open-pr', createGitHubStep({
action: 'createPR',
repo: 'AgentWorkforce/relay',
params: {
head: 'docs/readme-cleanup',
base: 'main',
title: 'docs: clean up README intro',
body: 'Lightly edited for clarity.',
},
}))
.run({ cwd: process.cwd() });Under the hood each createGitHubStep(...) call produces a type: 'integration' step — the runner schedules it, applies verification, and captures output the same way as any other step.
- Repositories —
listRepos,getRepo - Issues —
listIssues,createIssue,updateIssue,closeIssue - Pull requests —
listPRs,getPR,createPR,updatePR,mergePR - Files —
listFiles,readFile,createFile,updateFile,deleteFile - Branches + commits —
listBranches,createBranch,listCommits,createCommit - Identity —
getUser,listOrganizations
All actions work through the action + params shape. Outputs are typed — downstream steps can use {{steps.<name>.output}} to chain values through the workflow.
The primitive auto-picks the right backend for the environment it's running in:
| Mode | Triggered when |
|---|---|
local (via gh CLI) |
gh auth status succeeds and no cloud creds are set |
cloud (via Nango) |
NANGO_SECRET_KEY + NANGO_GITHUB_CONNECTION_ID + NANGO_GITHUB_PROVIDER_CONFIG_KEY are present |
cloud (via relay-cloud) |
RELAY_CLOUD_API_URL + RELAY_CLOUD_API_TOKEN + WORKSPACE_ID are present (fallback when Nango absent) |
Pick the default (runtime: 'auto') unless you need to pin one for testing. You can also set runtime per step via the config field — useful when the same workflow creates PRs across multiple tenants with different GitHub App installs.
Every cloud workspace can have its own GitHub App install — one Nango connection per tenant. createGitHubStep accepts a per-step config field so a single workflow can route different actions through different connections:
createGitHubStep({
action: 'createPR',
repo: 'AgentWorkforce/cloud',
params: { title, head, base, body },
config: await githubConfigForRepo({
repo: 'AgentWorkforce/cloud',
workspaceId: process.env.RELAY_WORKSPACE_ID,
}),
});The primitive itself stays tenant-unaware — it takes a GitHubRuntimeConfig and does what it's told. Tenant lookup lives in your app (typically a connection-resolver helper). Adding a new GitHub App install is a config row, not a code change.
- Workflows introduction — where this primitive shines.
- Patterns — canonical workflow shapes that commonly use GitHub steps (PR review loops, multi-repo shipping, etc.).
- Authentication — credentials model for the cloud runtime modes.