Examples
Complete workflow examples
Examples
Complete workflow examples demonstrating common patterns.
Feature Development
A complete workflow for implementing features:
import { defineNodes, defineWorkflow, StdlibTool } from '@sys/graph';
interface FeatureContext extends Record<string, unknown> {
request: string;
plan?: { tasks: string[] };
currentTask?: string;
completedTasks: string[];
allTasksDone: boolean;
lastCommandResult?: { exitCode: number; stdout: string; stderr: string };
}
const schema = defineNodes<FeatureContext>()([
'PLAN',
'IMPLEMENT',
'TEST',
'FIX',
'COMMIT',
] as const);
export default defineWorkflow({
id: 'feature-development',
schema,
initialContext: {
request: '',
completedTasks: [],
allTasksDone: false,
},
nodes: [
schema.agent('PLAN', {
role: 'architect',
prompt: `You are a Tech Lead. Analyze the feature request and create a task plan.
Output JSON: { "tasks": ["task1", "task2", ...] }`,
capabilities: [StdlibTool.Glob, StdlibTool.Read],
then: 'IMPLEMENT',
}),
schema.agent('IMPLEMENT', {
role: 'builder',
prompt: 'Implement the current task from the plan.',
capabilities: [StdlibTool.Write, StdlibTool.Read, StdlibTool.Bash],
then: (state) => (state.context.allTasksDone ? 'TEST' : 'IMPLEMENT'),
}),
schema.command('TEST', {
command: 'bun test',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'COMMIT';
}
return 'FIX';
},
}),
schema.agent('FIX', {
role: 'debugger',
prompt: 'Fix the failing tests based on the error output.',
capabilities: [StdlibTool.Read, StdlibTool.Write],
then: 'TEST',
}),
schema.slashCommand('COMMIT', {
command: 'commit',
args: 'Implement feature with passing tests',
then: 'END',
}),
],
});
Bug Fix Workflow
Systematic approach to fixing bugs:
import { defineNodes, defineWorkflow, StdlibTool } from '@sys/graph';
interface BugFixContext extends Record<string, unknown> {
bugId: string;
description: string;
reproduced: boolean;
fixed: boolean;
lastCommandResult?: { exitCode: number };
}
const schema = defineNodes<BugFixContext>()([
'REPRODUCE',
'FIX',
'VERIFY',
'COMMIT',
] as const);
export default defineWorkflow({
id: 'bug-fix',
schema,
initialContext: {
bugId: '',
description: '',
reproduced: false,
fixed: false,
},
nodes: [
schema.agent('REPRODUCE', {
role: 'debugger',
prompt: `Analyze the bug report and create a reproduction test.
Write a failing test that demonstrates the bug.`,
capabilities: [StdlibTool.Read, StdlibTool.Write, StdlibTool.Bash],
then: 'FIX',
}),
schema.agent('FIX', {
role: 'developer',
prompt: 'Fix the bug. The reproduction test should pass after your fix.',
capabilities: [StdlibTool.Read, StdlibTool.Write],
then: 'VERIFY',
}),
schema.command('VERIFY', {
command: 'bun test --grep "bug-"',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'COMMIT';
}
return 'FIX';
},
}),
schema.slashCommand('COMMIT', {
command: 'commit',
args: 'Fix bug with regression test',
then: 'END',
}),
],
});
Code Review Pipeline
Automated code review with AI:
import { defineNodes, defineWorkflow, StdlibTool } from '@sys/graph';
interface ReviewContext extends Record<string, unknown> {
prNumber: number;
files?: string[];
feedback?: string;
approved: boolean;
lastCommandResult?: { exitCode: number; stdout: string };
}
const schema = defineNodes<ReviewContext>()([
'FETCH_PR',
'ANALYZE',
'COMMENT',
'APPROVE',
] as const);
export default defineWorkflow({
id: 'code-review',
schema,
initialContext: {
prNumber: 0,
approved: false,
},
nodes: [
schema.command('FETCH_PR', {
command: 'gh pr view --json files,body',
then: 'ANALYZE',
}),
schema.agent('ANALYZE', {
role: 'reviewer',
prompt: `You are a senior code reviewer. Analyze the PR changes.
Focus on:
- Code quality and best practices
- Potential bugs or security issues
- Test coverage
- Documentation
Provide constructive feedback.`,
capabilities: [StdlibTool.Read, StdlibTool.Glob],
then: 'COMMENT',
}),
schema.command('COMMENT', {
command: 'gh pr comment --body "$REVIEW_COMMENT"',
then: (state) => {
if (state.context.approved) {
return 'APPROVE';
}
return 'END';
},
}),
schema.command('APPROVE', {
command: 'gh pr review --approve',
then: 'END',
}),
],
});
GitHub Projects Integration
Workflow with status tracking:
import { defineNodes, defineWorkflow, StdlibTool } from '@sys/graph';
import { createGitHubProjectNode } from '@sys/graph/nodes';
interface IssueContext extends Record<string, unknown> {
issueNumber: number;
title: string;
lastCommandResult?: { exitCode: number };
}
const schema = defineNodes<IssueContext>()([
'START',
'IMPLEMENT',
'TEST',
'FIX',
'REVIEW',
'CREATE_PR',
'DONE',
] as const);
const projectConfig = {
token: process.env.GITHUB_TOKEN!,
projectOwner: 'my-org',
projectNumber: 1,
owner: 'my-org',
repo: 'my-app',
issueNumberKey: 'issueNumber' as const,
};
export default defineWorkflow({
id: 'issue-workflow',
schema,
initialContext: {
issueNumber: 0,
title: '',
},
nodes: [
createGitHubProjectNode({
...projectConfig,
updates: { type: 'single_select', field: 'Status', value: 'In Progress' },
then: 'IMPLEMENT',
}),
schema.agent('IMPLEMENT', {
role: 'developer',
prompt: 'Implement the feature described in the issue.',
capabilities: [StdlibTool.Read, StdlibTool.Write, StdlibTool.Bash],
then: 'TEST',
}),
schema.command('TEST', {
command: 'bun test',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'REVIEW';
}
return 'FIX';
},
}),
schema.agent('FIX', {
role: 'debugger',
prompt: 'Fix the failing tests.',
capabilities: [StdlibTool.Read, StdlibTool.Write],
then: 'TEST',
}),
createGitHubProjectNode({
...projectConfig,
updates: { type: 'single_select', field: 'Status', value: 'In Review' },
then: 'CREATE_PR',
}),
schema.command('CREATE_PR', {
command: 'gh pr create --fill',
then: 'DONE',
}),
createGitHubProjectNode({
...projectConfig,
updates: { type: 'single_select', field: 'Status', value: 'Done' },
then: 'END',
}),
],
});
Deployment Pipeline
Multi-stage deployment with rollback:
import { defineNodes, defineWorkflow, StdlibTool } from '@sys/graph';
interface DeployContext extends Record<string, unknown> {
environment: 'staging' | 'production';
version: string;
previousVersion?: string;
deployedAt?: string;
lastCommandResult?: { exitCode: number; stdout: string; stderr: string };
}
const schema = defineNodes<DeployContext>()([
'BUILD',
'TEST',
'DEPLOY',
'VERIFY',
'ROLLBACK',
'SUCCESS',
'BUILD_FAILED',
'TEST_FAILED',
'FAILED',
] as const);
export default defineWorkflow({
id: 'deployment',
schema,
initialContext: {
environment: 'staging',
version: '',
},
nodes: [
schema.command('BUILD', {
command: 'bun run build',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'TEST';
}
return 'BUILD_FAILED';
},
}),
schema.command('TEST', {
command: 'bun test',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'DEPLOY';
}
return 'TEST_FAILED';
},
}),
schema.command('DEPLOY', {
command: 'railway deploy',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'VERIFY';
}
return 'ROLLBACK';
},
}),
schema.command('VERIFY', {
command: 'curl -f https://api.example.com/health',
then: (state) => {
if (state.context.lastCommandResult?.exitCode === 0) {
return 'SUCCESS';
}
return 'ROLLBACK';
},
}),
schema.agent('ROLLBACK', {
role: 'deployer',
prompt: 'Rollback to the previous version.',
capabilities: [StdlibTool.Bash],
then: 'FAILED',
}),
schema.slashCommand('SUCCESS', {
command: 'commit',
args: 'Deployment successful',
then: 'END',
}),
schema.agent('BUILD_FAILED', {
role: 'analyst',
prompt: 'Analyze build failure and suggest fixes.',
capabilities: [StdlibTool.Read],
then: 'END',
}),
schema.agent('TEST_FAILED', {
role: 'analyst',
prompt: 'Analyze test failures and suggest fixes.',
capabilities: [StdlibTool.Read],
then: 'END',
}),
schema.slashCommand('FAILED', {
command: 'commit',
args: 'Deployment failed - rolled back',
then: 'END',
}),
],
});
Custom Tools Example
Workflow with custom inline tools:
import { defineNodes, defineWorkflow, StdlibTool, type InlineTool } from '@sys/graph';
import { z } from 'zod';
interface AnalysisContext extends Record<string, unknown> {
filePath: string;
metrics?: {
complexity: number;
lines: number;
functions: number;
};
}
// Custom tool definitions
const calculateComplexity: InlineTool<{ filePath: string }> = {
name: 'calculate_complexity',
description: 'Calculate cyclomatic complexity of a file',
schema: z.object({
filePath: z.string(),
}),
execute: async ({ filePath }) => {
// Custom complexity calculation
const content = await Bun.file(filePath).text();
const complexity = countBranches(content);
return { complexity };
},
};
const countFunctionsTool: InlineTool<{ filePath: string }> = {
name: 'count_functions',
description: 'Count functions in a file',
schema: z.object({
filePath: z.string(),
}),
execute: async ({ filePath }) => {
const content = await Bun.file(filePath).text();
const functions = countFunctions(content);
return { count: functions };
},
};
const schema = defineNodes<AnalysisContext>()([
'ANALYZE',
'REPORT',
] as const);
export default defineWorkflow({
id: 'code-analysis',
schema,
initialContext: {
filePath: '',
},
nodes: [
schema.agent('ANALYZE', {
role: 'analyzer',
prompt: 'Analyze the code structure and quality.',
capabilities: [
StdlibTool.Read,
calculateComplexity,
countFunctionsTool,
],
then: 'REPORT',
}),
schema.agent('REPORT', {
role: 'reporter',
prompt: 'Generate a code quality report based on the analysis.',
capabilities: [StdlibTool.Write],
then: 'END',
}),
],
});
// Helper functions (implement as needed)
function countBranches(content: string): number {
const branches = content.match(/if|else|switch|case|for|while|\?/g);
return branches?.length ?? 0;
}
function countFunctions(content: string): number {
const functions = content.match(/function\s+\w+|=>\s*{|\w+\s*\([^)]*\)\s*{/g);
return functions?.length ?? 0;
}
Running Examples
# Run dispatch workflow (finds ready issues)
GRAPH_SOURCE=project GRAPH_PROJECT_NUMBER=14 bun run graph dispatch.config.ts
# Run issue processor workflow
GRAPH_ISSUE_NUMBER=123 bun run graph issue-processor.config.ts
# With verbose logging
bun run graph issue-processor.config.ts --verbose
# See all environment variables
bun run graph --help
Create your own workflow config file to run custom workflows:
// my-workflow.config.ts
export { myWorkflow as default } from './src/workflows/my-workflow';
Then run it:
bun run graph my-workflow.config.ts