-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy path60a-github-coding-agent-simple.ts
More file actions
156 lines (139 loc) · 5.85 KB
/
Copy path60a-github-coding-agent-simple.ts
File metadata and controls
156 lines (139 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* 60a - GitHub Coding Agent (simplified) — pick an issue, code the fix, create a PR.
*
* Uses built-in code execution (localCodeExecution: true) so the LLM
* composes shell commands naturally -- zero custom tool definitions.
*
* Requirements:
* - Conductor server running
* - CONDUCTOR_SERVER_URL=http://localhost:8080/api as environment variable
* - gh CLI authenticated
* - Git configured with push access to the repo
*/
import { Agent, AgentRuntime, OnTextMention } from '@io-orkes/conductor-javascript/agents';
import { randomBytes } from 'crypto';
const REPO = 'agentspan/codingexamples';
const WORK_DIR = `/tmp/codingexamples-${randomBytes(4).toString('hex')}`;
// -- GitHub Agent ------------------------------------------------------------
export const githubAgent = new Agent({
name: 'github_agent',
model: 'anthropic/claude-sonnet-4-20250514',
instructions:
'You are a GitHub operations specialist.\n\n' +
`Repo: ${REPO}\nWork dir: ${WORK_DIR}\n\n` +
'IMPORTANT: Read conversation history carefully.\n\n' +
'PHASE 1 -- SETUP:\n' +
`1. List issues: gh issue list --repo ${REPO} --state open --json number,title,body\n` +
'2. Pick the most suitable issue\n' +
`3. Clone: gh repo clone ${REPO} ${WORK_DIR}\n` +
`4. Branch: cd ${WORK_DIR} && git checkout -b feature/issue-N-desc\n` +
'5. Call transfer_to_coder with the issue details.\n\n' +
'PHASE 2 -- PR CREATION:\n' +
`6. Commit: cd ${WORK_DIR} && git add -A && git commit -m "Fix #N: desc" && git push -u origin HEAD\n` +
`7. Create PR: gh pr create --repo ${REPO} --title "Fix #N: title" --body "Description."\n` +
'8. Output the PR URL. Do NOT call any transfer tool after this.',
codeExecutionConfig: { enabled: true },
thinkingBudgetTokens: 4096,
maxTokens: 16384,
});
// -- Coder -------------------------------------------------------------------
export const coder = new Agent({
name: 'coder',
model: 'anthropic/claude-sonnet-4-20250514',
instructions:
'You are an expert developer.\n\n' +
`The repo is cloned at ${WORK_DIR}.\n\n` +
'WHEN YOU RECEIVE A TASK:\n' +
`1. Explore: find ${WORK_DIR} -type f -not -path "*/.git/*"\n` +
'2. Write ALL files in a SINGLE bash execution using heredocs\n' +
'3. Test your code to verify it works\n' +
'4. Call transfer_to_qa_tester for review\n\n' +
'IMPORTANT: You can ONLY use transfer_to_qa_tester.\n' +
'Each tool call uses one turn. Minimize turns by combining commands.',
codeExecutionConfig: { enabled: true },
thinkingBudgetTokens: 4096,
maxTokens: 16384,
});
// -- QA Tester ---------------------------------------------------------------
export const qaTester = new Agent({
name: 'qa_tester',
model: 'anthropic/claude-sonnet-4-20250514',
instructions:
'You are a meticulous QA engineer.\n\n' +
`The repo is at ${WORK_DIR}. You can read files with:\n cat ${WORK_DIR}/src/main.py\n\n` +
'Include ALL necessary code in each execution.\n\n' +
'TRANSFER RULES:\n' +
' bugs found -> call transfer_to_coder\n' +
' all tests pass -> call transfer_to_github_agent\n' +
' NEVER call transfer_to_coding_team',
codeExecutionConfig: { enabled: true },
thinkingBudgetTokens: 4096,
maxTokens: 16384,
});
// -- Coding Team: swarm coordinator ------------------------------------------
export const codingTeam = new Agent({
name: 'coding_team',
model: 'anthropic/claude-sonnet-4-20250514',
instructions:
'You are a coding team coordinator. Delegate to github_agent. ' +
'Call transfer_to_github_agent now.',
agents: [githubAgent, coder, qaTester],
strategy: 'swarm',
handoffs: [
new OnTextMention({ text: 'transfer_to_github_agent', target: 'github_agent' }),
new OnTextMention({ text: 'transfer_to_coder', target: 'coder' }),
new OnTextMention({ text: 'transfer_to_qa_tester', target: 'qa_tester' }),
],
allowedTransitions: {
coding_team: ['github_agent'],
github_agent: ['coder'],
coder: ['qa_tester'],
qa_tester: ['coder', 'github_agent'],
},
maxTurns: 30,
timeoutSeconds: 900,
});
// -- Run ---------------------------------------------------------------------
const prompt =
'Pick an open issue from the GitHub repository, implement the ' +
'feature or fix the bug, get it reviewed by QA, and create a PR.';
async function main() {
const runtime = new AgentRuntime();
try {
console.log('='.repeat(60));
console.log(' GitHub Coding Agent (Simplified)');
console.log(` Repo: ${REPO}`);
console.log(` Work dir: ${WORK_DIR}`);
console.log(' coding_team -> github_agent <-> coder <-> qa_tester (swarm)');
console.log(' Tools: built-in code execution (any language)');
console.log('='.repeat(60));
console.log(`\nPrompt: ${prompt}\n`);
const result = await runtime.run(codingTeam, prompt);
const output = result.output;
const skipKeys = new Set(['finishReason', 'rejectionReason', 'is_transfer', 'transfer_to']);
if (output && typeof output === 'object' && !Array.isArray(output)) {
for (const [key, text] of Object.entries(output as Record<string, string>)) {
if (skipKeys.has(key) || !text) continue;
console.log(`\n${'─'.repeat(60)}`);
console.log(` [${key}]`);
console.log('─'.repeat(60));
console.log(text);
}
} else {
console.log(output);
}
console.log(`\nFinish reason: ${result.finishReason}`);
console.log(`Execution ID: ${result.executionId}`);
// Production pattern:
// 1. Deploy once during CI/CD (optional -- serve() below also deploys):
// await runtime.deploy(codingTeam);
// CLI alternative:
// agentspan deploy --package sdk/typescript/examples --agents coding_team
//
// 2. In a separate long-lived worker process (deploys + registers workers + starts polling):
// await runtime.serve(codingTeam);
} finally {
await runtime.shutdown();
}
}
main().catch(console.error);