Repository navigation
Expand file tree
/
Copy pathdeepagents-example.yml.example
More file actions
218 lines (189 loc) · 9.86 KB
/
Copy pathdeepagents-example.yml.example
File metadata and controls
218 lines (189 loc) · 9.86 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
name: Deep Agents Example
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
workflow_dispatch:
inputs:
prompt:
description: "Prompt for the agent"
required: true
# Cancel superseded runs when @deepagents is mentioned multiple times on the same PR/issue
concurrency:
group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
deepagents:
if: |
github.event_name == 'workflow_dispatch' ||
(
contains(github.event.comment.body, '@deepagents') &&
(
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR'
) &&
(
github.event_name == 'pull_request_review_comment' ||
github.event.issue.pull_request
)
)
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
steps:
- name: Resolve PR number
if: github.event_name != 'workflow_dispatch'
id: pr-info
shell: bash
env:
GH_TOKEN: ${{ github.token }}
# issue_comment uses event.issue.number; review_comment uses event.pull_request.number
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
run: |
echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
- name: Acknowledge trigger
if: github.event_name != 'workflow_dispatch'
continue-on-error: true
shell: bash
env:
GH_TOKEN: ${{ github.token }}
COMMENT_ID: ${{ github.event.comment.id }}
EVENT_NAME: ${{ github.event_name }}
REPO: ${{ github.repository }}
run: |
# issue_comment reactions use issues/comments; review_comment uses pulls/comments
if [ "$EVENT_NAME" = "pull_request_review_comment" ]; then
API_PATH="repos/${REPO}/pulls/comments/${COMMENT_ID}/reactions"
else
API_PATH="repos/${REPO}/issues/comments/${COMMENT_ID}/reactions"
fi
if ! gh api --method POST "$API_PATH" -f content='rocket'; then
echo "::warning::Failed to add reaction to comment ${COMMENT_ID} — comment may have been deleted or token may lack permissions"
fi
- name: Get PR head SHA
if: github.event_name != 'workflow_dispatch'
id: pr-sha
shell: bash
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.pr-info.outputs.number }}
run: |
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json headRefOid,headRefName)
PR_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')
PR_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
if [ -z "$PR_SHA" ] || [ "$PR_SHA" = "null" ] || [ -z "$PR_BRANCH" ] || [ "$PR_BRANCH" = "null" ]; then
echo "::error::Failed to resolve PR head for #${PR_NUMBER}. API response: ${PR_DATA}"
exit 1
fi
echo "sha=$PR_SHA" >> "$GITHUB_OUTPUT"
echo "branch=$PR_BRANCH" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# Use the PR branch name so the agent can commit and push to the PR directly.
ref: ${{ github.event_name != 'workflow_dispatch' && steps.pr-sha.outputs.branch || '' }}
- name: Build PR context prompt
if: github.event_name != 'workflow_dispatch'
id: build-prompt
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TRIGGER_COMMENT_BODY: ${{ github.event.comment.body }}
TRIGGER_COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
PR_NUMBER: ${{ steps.pr-info.outputs.number }}
run: |
PROMPT_FILE=$(mktemp)
GH_STDERR=$(mktemp)
trap 'rm -f "$PROMPT_FILE" "$GH_STDERR"' EXIT
# Fetch PR data
if ! PR_DATA=$(gh pr view "$PR_NUMBER" --json title,body,author,state,headRefName,baseRefName 2>"$GH_STDERR"); then
echo "::error::Failed to fetch PR #${PR_NUMBER} data: $(cat "$GH_STDERR"). Check that the PR exists and the token has 'pull-requests: read' permission."
exit 1
fi
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title // "Untitled"')
PR_BODY=$(echo "$PR_DATA" | jq -r '.body // "No description"')
PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login // "unknown"')
PR_STATE=$(echo "$PR_DATA" | jq -r '.state // "unknown"')
PR_HEAD=$(echo "$PR_DATA" | jq -r '.headRefName // "unknown"')
PR_BASE=$(echo "$PR_DATA" | jq -r '.baseRefName // "unknown"')
# Fetch PR diff stats (first page)
if ! DIFF_STAT=$(gh pr diff "$PR_NUMBER" --name-only 2>"$GH_STDERR"); then
echo "::warning::Failed to fetch PR diff: $(cat "$GH_STDERR")"
DIFF_STAT="[Error fetching diff — see workflow logs]"
fi
# Fetch PR comments (first 20 — older ones omitted)
if ! PR_COMMENTS=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments?per_page=20" \
--jq '.[] | "<comment author=\"\(.user.login)\">\(.body)</comment>"' 2>"$GH_STDERR"); then
echo "::warning::Failed to fetch PR comments: $(cat "$GH_STDERR")"
PR_COMMENTS="[Error fetching comments — see workflow logs]"
fi
# Fetch PR reviews (first 10)
if ! PR_REVIEWS=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews?per_page=10" \
--jq '.[] | "<review author=\"\(.user.login)\" state=\"\(.state)\">\(.body // "No review body")</review>"' 2>"$GH_STDERR"); then
echo "::warning::Failed to fetch PR reviews: $(cat "$GH_STDERR")"
PR_REVIEWS="[Error fetching reviews — see workflow logs]"
fi
# Fetch review comments / inline code comments (first 30)
if ! REVIEW_COMMENTS=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/comments?per_page=30" \
--jq '.[] | "<review-comment author=\"\(.user.login)\" path=\"\(.path)\" line=\"\(.line // .original_line)\">\(.body)</review-comment>"' 2>"$GH_STDERR"); then
echo "::warning::Failed to fetch review comments: $(cat "$GH_STDERR")"
REVIEW_COMMENTS="[Error fetching review comments — see workflow logs]"
fi
cat > "$PROMPT_FILE" << 'PROMPT_HEADER'
<instructions>
The user has tagged @deepagents in a comment on this pull request. Your task is to resolve their request in the simplest way possible.
You have shell access with git and gh available. The repository is checked out on the PR branch.
Determine whether the comment requires code changes, and if so implement them directly.
- Make only the changes requested. Do not make unrelated changes.
- Do not leave comments in your code about the request or changes you're making.
- Keep changes minimal and focused.
If the comment does not require code changes (e.g. a question), respond by creating a comment on the PR with your answer.
After making changes, commit them to the current branch.
IMPORTANT: When you are finished, you MUST post a brief summary comment on the PR using `gh pr comment`. The comment should:
- Briefly describe what you did (1-3 sentences)
- List any files changed or commits made
- Note if you were unable to complete any part of the request
Always post this summary, even if the task was simple or no code changes were needed.
</instructions>
PROMPT_HEADER
# Write PR context using printf to avoid shell expansion of user-controlled content
{
printf '<pull-request>\n'
printf '<title>%s</title>\n' "$PR_TITLE"
printf '<author>%s</author>\n' "$PR_AUTHOR"
printf '<state>%s</state>\n' "$PR_STATE"
printf '<base>%s</base>\n' "$PR_BASE"
printf '<head>%s</head>\n' "$PR_HEAD"
printf '<body>\n%s\n</body>\n' "$PR_BODY"
printf '</pull-request>\n\n'
printf '<changed-files>\n%s\n</changed-files>\n\n' "$DIFF_STAT"
printf '<pull-request-comments>\n%s\n</pull-request-comments>\n\n' "$PR_COMMENTS"
printf '<pull-request-reviews>\n%s\n</pull-request-reviews>\n\n' "$PR_REVIEWS"
printf '<review-comments>\n%s\n</review-comments>\n\n' "$REVIEW_COMMENTS"
printf '<trigger-comment>\n'
printf 'This is the comment that triggered this workflow. Focus on resolving this request.\n'
printf '<author>%s</author>\n' "$TRIGGER_COMMENT_AUTHOR"
printf '<body>\n%s\n</body>\n' "$TRIGGER_COMMENT_BODY"
printf '</trigger-comment>\n\n'
printf 'Given all of this context, resolve the trigger comment in the simplest way possible.\n'
printf 'IMPORTANT: The trigger comment takes precedence. Focus on what was asked, using the PR context to inform your approach.\n'
} >> "$PROMPT_FILE"
# Set output using heredoc with random delimiter
DELIMITER="PROMPT_$(openssl rand -hex 16)"
{
echo "prompt<<${DELIMITER}"
cat "$PROMPT_FILE"
echo "${DELIMITER}"
} >> "$GITHUB_OUTPUT"
- name: Run Deep Agents
uses: langchain-ai/deepagents@main
with:
prompt: ${{ github.event_name != 'workflow_dispatch' && steps.build-prompt.outputs.prompt || github.event.inputs.prompt }}
model: claude-sonnet-4-6
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# Or: openai_api_key: ${{ secrets.OPENAI_API_KEY }}
# Or: google_api_key: ${{ secrets.GOOGLE_API_KEY }}
skills_repo: langchain-ai/langchain-skills