-
Notifications
You must be signed in to change notification settings - Fork 2
230 lines (218 loc) · 10.7 KB
/
agent-orchestrator.yml
File metadata and controls
230 lines (218 loc) · 10.7 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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
name: Agent / Orchestrator
on:
workflow_dispatch:
inputs:
source_action:
description: "Agent action that handed back to the orchestrator"
required: true
source_conclusion:
description: "Normalized source action conclusion"
required: true
source_recommended_next_step:
description: "Optional source action recommended next step"
required: false
default: ""
source_run_id:
description: "Workflow run ID of the source action, used for handoff dedupe"
required: false
default: ""
target_number:
description: "Issue or pull request number currently being handled"
required: true
target_kind:
description: "Issue or pull request kind currently being handled"
required: false
default: ""
author_association:
description: "Original requester author association from router context"
required: false
default: ""
access_policy:
description: "Route access policy JSON used by router authorization"
required: false
default: ""
repository_private:
description: "Repository visibility flag for access policy defaults"
required: false
default: ""
next_target_number:
description: "Optional next target number produced by the source action"
required: false
default: ""
source_handoff_context:
description: "Optional action-oriented context derived by the source action"
required: false
default: ""
requested_by:
description: "GitHub login that requested the original run"
required: false
request_text:
description: "Original user request text forwarded from the source action"
required: false
session_bundle_mode:
description: "Session bundle persistence mode"
required: false
default: ""
base_branch:
description: "Branch to pass to agent-implement when dispatching an implementation"
required: false
default: ""
base_pr:
description: "Open PR number whose head branch agent-implement should stack on"
required: false
default: ""
automation_mode:
description: "Post-action orchestration mode (disabled, heuristics, agent)"
required: false
default: "disabled"
automation_current_round:
description: "Current automation handoff round"
required: false
default: "1"
automation_max_rounds:
description: "Maximum automation handoff rounds"
required: false
default: "12"
permissions:
actions: write
contents: read
issues: write
pull-requests: read
id-token: write # required for GitHub Actions OIDC broker exchange
concurrency:
group: agent-orchestrator-${{ github.repository }}-${{ inputs.target_number }}-${{ inputs.source_action }}-${{ inputs.automation_current_round }}
cancel-in-progress: false
jobs:
orchestrate:
if: vars.AGENT_ENABLED != 'false'
runs-on: ${{ fromJson(vars.AGENT_RUNS_ON || '["ubuntu-latest"]') }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
token: ${{ github.token }}
- name: Resolve GitHub auth
id: auth
uses: ./.github/actions/resolve-github-auth
with:
app_id: ${{ secrets.AGENT_APP_ID }}
app_private_key: ${{ secrets.AGENT_APP_PRIVATE_KEY }}
pat: ${{ secrets.AGENT_PAT }}
fallback_token: ${{ github.token }}
- name: Setup agent runtime
uses: ./.github/actions/setup-agent-runtime
- name: Check handoff preflight
id: preflight
env:
AUTOMATION_CURRENT_ROUND: ${{ inputs.automation_current_round }}
AUTOMATION_MAX_ROUNDS: ${{ inputs.automation_max_rounds }}
AUTOMATION_MODE: ${{ inputs.automation_mode }}
SOURCE_ACTION: ${{ inputs.source_action }}
SOURCE_CONCLUSION: ${{ inputs.source_conclusion }}
TARGET_KIND: ${{ inputs.target_kind || (inputs.source_action == 'implement' && 'issue' || 'pull_request') }}
AGENT_ALLOW_SELF_APPROVE: ${{ vars.AGENT_ALLOW_SELF_APPROVE || 'false' }}
AGENT_ALLOW_SELF_MERGE: ${{ vars.AGENT_ALLOW_SELF_MERGE || 'false' }}
AUTHOR_ASSOCIATION: ${{ inputs.author_association }}
ACCESS_POLICY: ${{ inputs.access_policy }}
REPOSITORY_PRIVATE: ${{ inputs.repository_private || (github.event.repository.private && 'true' || 'false') }}
run: node .agent/dist/cli/orchestrator-preflight.js
- name: Resolve orchestrator provider
id: provider
if: ${{ steps.preflight.outputs.planner_enabled == 'true' }}
uses: ./.github/actions/resolve-agent-provider
with:
route: orchestrator
default_provider: ${{ vars.AGENT_DEFAULT_PROVIDER || 'auto' }}
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
model_policy: ${{ vars.AGENT_MODEL_POLICY || '' }}
- name: Install orchestrator provider
if: ${{ steps.preflight.outputs.planner_enabled == 'true' }}
uses: ./.github/actions/setup-agent-runtime
with:
install_codex: ${{ steps.provider.outputs.install_codex }}
install_claude: ${{ steps.provider.outputs.install_claude }}
- name: Resolve task timeout
if: ${{ steps.preflight.outputs.planner_enabled == 'true' }}
id: task_timeout
env:
AGENT_TASK_TIMEOUT_POLICY: ${{ vars.AGENT_TASK_TIMEOUT_POLICY || '' }}
ROUTE: orchestrator
run: node .agent/dist/cli/resolve-task-timeout.js
- name: Plan next action with agent
id: planner
if: ${{ steps.preflight.outputs.planner_enabled == 'true' }}
continue-on-error: true
timeout-minutes: ${{ fromJson(steps.task_timeout.outputs.minutes || '30') }}
uses: ./.github/actions/run-agent-task
env:
ORCHESTRATOR_SOURCE_ACTION: ${{ inputs.source_action }}
ORCHESTRATOR_SOURCE_CONCLUSION: ${{ inputs.source_conclusion }}
ORCHESTRATOR_SOURCE_RECOMMENDED_NEXT_STEP: ${{ inputs.source_recommended_next_step }}
ORCHESTRATOR_SOURCE_RUN_ID: ${{ inputs.source_run_id || github.run_id }}
ORCHESTRATOR_NEXT_TARGET_NUMBER: ${{ inputs.next_target_number }}
ORCHESTRATOR_SOURCE_HANDOFF_CONTEXT: ${{ inputs.source_handoff_context }}
ORCHESTRATOR_SELF_APPROVE_ENABLED: ${{ vars.AGENT_ALLOW_SELF_APPROVE || 'false' }}
ORCHESTRATOR_SELF_MERGE_ENABLED: ${{ vars.AGENT_ALLOW_SELF_MERGE || 'false' }}
ORCHESTRATOR_CURRENT_ROUND: ${{ inputs.automation_current_round }}
ORCHESTRATOR_MAX_ROUNDS: ${{ inputs.automation_max_rounds }}
with:
agent: ${{ steps.provider.outputs.provider }}
github_token: ${{ steps.auth.outputs.token }}
secondary_github_token: ${{ secrets.AGENT_SECONDARY_GITHUB_TOKEN }}
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
model: ${{ steps.provider.outputs.model }}
display_model: ${{ vars.AGENT_DISPLAY_MODEL || '' }}
permission_mode: approve-all
prompt: orchestrator
reasoning_effort: ${{ steps.provider.outputs.reasoning_effort || 'high' }}
lane: planner
memory_mode_override: read-only
memory_ref: ${{ vars.AGENT_MEMORY_REF || 'agent/memory' }}
memory_policy: ${{ vars.AGENT_MEMORY_POLICY || '' }}
rubrics_ref: ${{ vars.AGENT_RUBRICS_REF || 'agent/rubrics' }}
rubrics_policy: ${{ vars.AGENT_RUBRICS_POLICY || '' }}
rubrics_mode_override: read-only
rubrics_limit: ${{ vars.AGENT_RUBRICS_LIMIT || '10' }}
session_bundle_mode: ${{ inputs.session_bundle_mode || vars.AGENT_SESSION_BUNDLE_MODE || 'auto' }}
session_policy: resume-best-effort
request_text: ${{ inputs.request_text }}
requested_by: ${{ inputs.requested_by || github.actor }}
route: orchestrator
source_kind: workflow_dispatch
target_kind: ${{ inputs.target_kind || (inputs.source_action == 'implement' && 'issue' || 'pull_request') }}
target_number: ${{ inputs.target_number }}
target_url: ${{ (inputs.target_kind || (inputs.source_action == 'implement' && 'issue' || 'pull_request')) == 'issue' && format('{0}/{1}/issues/{2}', github.server_url, github.repository, inputs.target_number) || format('{0}/{1}/pull/{2}', github.server_url, github.repository, inputs.target_number) }}
workflow: agent-orchestrator.yml
- name: Decide and dispatch next action
env:
AUTOMATION_CURRENT_ROUND: ${{ inputs.automation_current_round }}
AUTOMATION_MAX_ROUNDS: ${{ inputs.automation_max_rounds }}
AUTOMATION_MODE: ${{ inputs.automation_mode }}
AGENT_COLLAPSE_OLD_REVIEWS: ${{ vars.AGENT_COLLAPSE_OLD_REVIEWS }}
BASE_BRANCH: ${{ inputs.base_branch }}
BASE_PR: ${{ inputs.base_pr }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GH_TOKEN: ${{ steps.auth.outputs.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
NEXT_TARGET_NUMBER: ${{ inputs.next_target_number }}
REQUESTED_BY: ${{ inputs.requested_by || github.actor }}
REQUEST_TEXT: ${{ inputs.request_text }}
SESSION_BUNDLE_MODE: ${{ inputs.session_bundle_mode || vars.AGENT_SESSION_BUNDLE_MODE || 'auto' }}
SOURCE_ACTION: ${{ inputs.source_action }}
SOURCE_CONCLUSION: ${{ inputs.source_conclusion }}
SOURCE_RECOMMENDED_NEXT_STEP: ${{ inputs.source_recommended_next_step }}
SOURCE_HANDOFF_CONTEXT: ${{ inputs.source_handoff_context }}
SOURCE_RUN_ID: ${{ inputs.source_run_id || github.run_id }}
AGENT_ALLOW_SELF_APPROVE: ${{ vars.AGENT_ALLOW_SELF_APPROVE || 'false' }}
AGENT_ALLOW_SELF_MERGE: ${{ vars.AGENT_ALLOW_SELF_MERGE || 'false' }}
AUTHOR_ASSOCIATION: ${{ inputs.author_association }}
ACCESS_POLICY: ${{ inputs.access_policy }}
REPOSITORY_PRIVATE: ${{ inputs.repository_private || (github.event.repository.private && 'true' || 'false') }}
TARGET_KIND: ${{ inputs.target_kind || (inputs.source_action == 'implement' && 'issue' || 'pull_request') }}
TARGET_NUMBER: ${{ inputs.target_number }}
PLANNER_RESPONSE_FILE: ${{ steps.planner.outputs.response_file }}
run: node .agent/dist/cli/orchestrate-handoff.js