Skip to content

Commit 13014fb

Browse files
authored
Merge pull request #126 from Automattic/docs-agent-consumer
Add reusable Docs Agent workflow
2 parents 4c9c949 + 25f6a48 commit 13014fb

3 files changed

Lines changed: 384 additions & 0 deletions

File tree

.github/workflows/docs-agent.yml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
name: Docs Agent
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
prompt:
7+
description: Instruction for Docs Agent.
8+
required: true
9+
default: Generate or update technical developer documentation for Agents API from source code. Open a documentation PR only if needed.
10+
openai_model:
11+
description: OpenAI model to use for the imported agent flow.
12+
required: true
13+
default: gpt-5.5
14+
docs_agent_ref:
15+
description: Docs Agent ref.
16+
required: true
17+
default: main
18+
data_machine_ref:
19+
description: Data Machine ref.
20+
required: true
21+
default: main
22+
data_machine_code_ref:
23+
description: Data Machine Code ref.
24+
required: true
25+
default: main
26+
homeboy_extensions_ref:
27+
description: Homeboy Extensions ref.
28+
required: true
29+
default: main
30+
homeboy_ref:
31+
description: Homeboy core ref.
32+
required: true
33+
default: main
34+
35+
permissions:
36+
contents: write
37+
pull-requests: write
38+
issues: write
39+
40+
jobs:
41+
docs-agent:
42+
name: Run Docs Agent
43+
runs-on: ubuntu-latest
44+
timeout-minutes: 45
45+
46+
steps:
47+
- name: Checkout Agents API
48+
uses: actions/checkout@v4
49+
with:
50+
fetch-depth: 0
51+
52+
- name: Checkout Docs Agent
53+
uses: actions/checkout@v4
54+
with:
55+
repository: Automattic/docs-agent
56+
ref: ${{ inputs.docs_agent_ref }}
57+
path: .ci/docs-agent
58+
59+
- name: Checkout Homeboy Extensions
60+
uses: actions/checkout@v4
61+
with:
62+
repository: Extra-Chill/homeboy-extensions
63+
ref: ${{ inputs.homeboy_extensions_ref }}
64+
path: .ci/homeboy-extensions
65+
66+
- name: Checkout Homeboy
67+
uses: actions/checkout@v4
68+
with:
69+
repository: Extra-Chill/homeboy
70+
ref: ${{ inputs.homeboy_ref }}
71+
path: .ci/homeboy
72+
73+
- name: Checkout Data Machine
74+
uses: actions/checkout@v4
75+
with:
76+
repository: Extra-Chill/data-machine
77+
ref: ${{ inputs.data_machine_ref }}
78+
path: .ci/data-machine
79+
80+
- name: Checkout Data Machine Code
81+
uses: actions/checkout@v4
82+
with:
83+
repository: Extra-Chill/data-machine-code
84+
ref: ${{ inputs.data_machine_code_ref }}
85+
path: .ci/data-machine-code
86+
87+
- name: Checkout OpenAI provider
88+
uses: actions/checkout@v4
89+
with:
90+
repository: WordPress/ai-provider-for-openai
91+
path: .ci/ai-provider-for-openai
92+
93+
- name: Set up Node.js
94+
uses: actions/setup-node@v4
95+
with:
96+
node-version: 24
97+
98+
- name: Install Homeboy WordPress extension dependencies
99+
working-directory: .ci/homeboy-extensions/wordpress
100+
run: |
101+
composer install --no-interaction --no-progress --prefer-dist
102+
npm install
103+
104+
- name: Install plugin PHP dependencies
105+
run: |
106+
composer install --working-dir=.ci/data-machine --no-interaction --no-progress --prefer-dist
107+
composer install --working-dir=.ci/data-machine-code --no-interaction --no-progress --prefer-dist
108+
109+
- name: Validate Docs Agent bundle
110+
working-directory: .ci/docs-agent
111+
run: php tests/validate-docs-agent-bundle.php
112+
113+
- name: Run Docs Agent
114+
env:
115+
GITHUB_TOKEN: ${{ github.token }}
116+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
117+
HOMEBOY_EXTENSION_PATH: ${{ github.workspace }}/.ci/homeboy-extensions/wordpress
118+
HOMEBOY_RUNTIME_BENCH_HELPER_SH: ${{ github.workspace }}/.ci/homeboy/src/core/extension/runtime/bench-helper.sh
119+
HOMEBOY_RUNTIME_BENCH_HELPER_PHP: ${{ github.workspace }}/.ci/homeboy/src/core/extension/runtime/bench-helper.php
120+
AGENTS_API_PATH: ${{ github.workspace }}
121+
DM_PATH: ${{ github.workspace }}/.ci/data-machine
122+
DMC_PATH: ${{ github.workspace }}/.ci/data-machine-code
123+
OPENAI_PROVIDER_PATH: ${{ github.workspace }}/.ci/ai-provider-for-openai
124+
DOCS_AGENT_OPENAI_MODEL: ${{ inputs.openai_model }}
125+
DOCS_AGENT_REF: ${{ inputs.docs_agent_ref }}
126+
DOCS_AGENT_WORKFLOW: technical
127+
DOCS_AGENT_TARGET_REPO: Automattic/agents-api
128+
DOCS_AGENT_PROMPT: ${{ inputs.prompt }}
129+
run: tests/playground-ci/scripts/run-docs-agent.sh
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
/**
3+
* Plugin Name: Agents API Docs Agent CI Driver
4+
* Description: Minimal Playground driver plugin for the reusable Docs Agent workflow.
5+
* Version: 0.1.0
6+
*/
7+
8+
defined( 'ABSPATH' ) || exit;
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
6+
COMPONENT_PATH="$REPO_ROOT/tests/playground-ci/component"
7+
8+
EXTENSION_PATH="${HOMEBOY_EXTENSION_PATH:-/Users/chubes/Developer/homeboy-extensions/wordpress}"
9+
AGENTS_API_PATH="${AGENTS_API_PATH:-$REPO_ROOT}"
10+
DM_PATH="${DM_PATH:-/Users/chubes/Developer/data-machine}"
11+
DMC_PATH="${DMC_PATH:-/Users/chubes/Developer/data-machine-code}"
12+
OPENAI_PROVIDER_PATH="${OPENAI_PROVIDER_PATH:-/Users/chubes/Studio/intelligence-chubes4/wp-content/plugins/ai-provider-for-openai}"
13+
STUDIO_SITE_PATH="${STUDIO_SITE_PATH:-/Users/chubes/Studio/intelligence-chubes4}"
14+
DOCS_AGENT_OPENAI_MODEL="${DOCS_AGENT_OPENAI_MODEL:-gpt-5.5}"
15+
DOCS_AGENT_TARGET_REPO="${DOCS_AGENT_TARGET_REPO:-Automattic/agents-api}"
16+
DOCS_AGENT_REF="${DOCS_AGENT_REF:-main}"
17+
DOCS_AGENT_WORKFLOW="${DOCS_AGENT_WORKFLOW:-technical}"
18+
DOCS_AGENT_PROMPT="${DOCS_AGENT_PROMPT:-Generate or update technical developer documentation for Agents API from source code. Open a documentation PR only if needed.}"
19+
20+
case "$DOCS_AGENT_WORKFLOW" in
21+
technical)
22+
DOCS_AGENT_PIPELINE_SLUG="technical-docs-pipeline"
23+
DOCS_AGENT_FLOW_SLUG="technical-docs-flow"
24+
DOCS_AGENT_WORKLOAD_ID="technical-docs-generation"
25+
DOCS_AGENT_WORKLOAD_LABEL="Run Docs Agent technical documentation"
26+
DOCS_AGENT_AUDIENCE="technical developer-facing"
27+
;;
28+
user)
29+
DOCS_AGENT_PIPELINE_SLUG="user-docs-pipeline"
30+
DOCS_AGENT_FLOW_SLUG="user-docs-flow"
31+
DOCS_AGENT_WORKLOAD_ID="user-docs-generation"
32+
DOCS_AGENT_WORKLOAD_LABEL="Run Docs Agent user documentation"
33+
DOCS_AGENT_AUDIENCE="non-technical user-facing"
34+
;;
35+
*)
36+
echo "ERROR: DOCS_AGENT_WORKFLOW must be technical or user" >&2
37+
exit 1
38+
;;
39+
esac
40+
41+
if [ ! -f "$EXTENSION_PATH/scripts/bench/bench-runner.sh" ]; then
42+
echo "ERROR: Homeboy WordPress extension not found at $EXTENSION_PATH" >&2
43+
exit 1
44+
fi
45+
if [ ! -d "$AGENTS_API_PATH" ] || [ ! -d "$DM_PATH" ] || [ ! -d "$DMC_PATH" ]; then
46+
echo "ERROR: Agents API, Data Machine, and Data Machine Code checkouts are required" >&2
47+
exit 1
48+
fi
49+
if [ ! -d "$OPENAI_PROVIDER_PATH" ]; then
50+
echo "ERROR: AI Provider for OpenAI plugin not found at $OPENAI_PROVIDER_PATH" >&2
51+
exit 1
52+
fi
53+
if ! command -v jq >/dev/null 2>&1; then
54+
echo "ERROR: jq required" >&2
55+
exit 1
56+
fi
57+
58+
GITHUB_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
59+
if [ -z "$GITHUB_TOKEN" ] && command -v gh >/dev/null 2>&1; then
60+
GITHUB_TOKEN="$(gh auth token 2>/dev/null || true)"
61+
fi
62+
if [ -z "$GITHUB_TOKEN" ]; then
63+
echo "ERROR: GITHUB_TOKEN or GH_TOKEN is required, or gh must be authenticated" >&2
64+
exit 1
65+
fi
66+
67+
OPENAI_API_KEY="${OPENAI_API_KEY:-}"
68+
if [ -z "$OPENAI_API_KEY" ] && command -v studio >/dev/null 2>&1 && [ -d "$STUDIO_SITE_PATH" ]; then
69+
OPENAI_API_KEY="$(cd "$STUDIO_SITE_PATH" && studio wp option get connectors_ai_openai_api_key 2>/dev/null || true)"
70+
fi
71+
if [ -z "$OPENAI_API_KEY" ]; then
72+
echo "ERROR: OPENAI_API_KEY is required, or the local Studio site must store connectors_ai_openai_api_key" >&2
73+
exit 1
74+
fi
75+
76+
CONFIG_TMPFILE=$(mktemp "${TMPDIR:-/tmp}/docs-agent-config.XXXXXX.json")
77+
RESULTS_TMPFILE=$(mktemp "${TMPDIR:-/tmp}/docs-agent-results.XXXXXX.json")
78+
TRANSCRIPT_ARTIFACT_DIR="$COMPONENT_PATH/artifacts/docs-agent"
79+
80+
cleanup() {
81+
rm -f "$CONFIG_TMPFILE" "$RESULTS_TMPFILE"
82+
}
83+
trap cleanup EXIT
84+
85+
rm -rf "$TRANSCRIPT_ARTIFACT_DIR"
86+
mkdir -p "$TRANSCRIPT_ARTIFACT_DIR"
87+
88+
HE_AGENT_RUNNER="$EXTENSION_PATH/scripts/agent/run-datamachine-agent.sh"
89+
if [ ! -f "$HE_AGENT_RUNNER" ]; then
90+
echo "ERROR: generic Data Machine agent runner not found at $HE_AGENT_RUNNER" >&2
91+
exit 1
92+
fi
93+
94+
EVENT_NAME="${GITHUB_EVENT_NAME:-manual}"
95+
TARGET_REF="${GITHUB_REF_NAME:-main}"
96+
HEAD_SHA="${GITHUB_SHA:-}"
97+
RUN_URL=""
98+
if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then
99+
RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
100+
fi
101+
102+
PROMPT=$(cat <<EOF
103+
${DOCS_AGENT_PROMPT}
104+
105+
Target repository: ${DOCS_AGENT_TARGET_REPO}
106+
Event name: ${EVENT_NAME}
107+
Target ref: ${TARGET_REF}
108+
Head SHA: ${HEAD_SHA}
109+
Workflow run: ${RUN_URL}
110+
Writable documentation paths: README.md, docs/**
111+
Selected docs workflow: ${DOCS_AGENT_WORKFLOW} (${DOCS_AGENT_AUDIENCE})
112+
113+
Generate documentation from source code for the selected audience. If no documentation update is needed, finish cleanly without opening a pull request. If an update is needed, write only allowed documentation paths and open one pull request.
114+
EOF
115+
)
116+
117+
jq -n \
118+
--arg componentPath "$COMPONENT_PATH" \
119+
--arg agentsApi "$AGENTS_API_PATH" \
120+
--arg dm "$DM_PATH" \
121+
--arg dmc "$DMC_PATH" \
122+
--arg openaiProvider "$OPENAI_PROVIDER_PATH" \
123+
--arg githubToken "$GITHUB_TOKEN" \
124+
--arg openaiKey "$OPENAI_API_KEY" \
125+
--arg model "$DOCS_AGENT_OPENAI_MODEL" \
126+
--arg targetRepo "$DOCS_AGENT_TARGET_REPO" \
127+
--arg docsAgentRef "$DOCS_AGENT_REF" \
128+
--arg pipelineSlug "$DOCS_AGENT_PIPELINE_SLUG" \
129+
--arg flowSlug "$DOCS_AGENT_FLOW_SLUG" \
130+
--arg workloadId "$DOCS_AGENT_WORKLOAD_ID" \
131+
--arg workloadLabel "$DOCS_AGENT_WORKLOAD_LABEL" \
132+
--arg prompt "$PROMPT" \
133+
'{
134+
component_id: "agents-api-docs-agent-ci-driver",
135+
component_path: $componentPath,
136+
workload_id: $workloadId,
137+
workload_label: $workloadLabel,
138+
validation_dependencies: [$agentsApi, $dm, $dmc, $openaiProvider],
139+
playground_wordpress_version: "7.0",
140+
bundle_repo: "https://github.com/Automattic/docs-agent.git",
141+
bundle_ref: $docsAgentRef,
142+
bundle_path_in_repo: "bundles/docs-agent",
143+
agent_slug: "docs-agent",
144+
pipeline_slug: $pipelineSlug,
145+
flow_slug: $flowSlug,
146+
provider: "openai",
147+
model: $model,
148+
provider_register_function: "WordPress\\OpenAiAiProvider\\register_provider",
149+
provider_credentials: {
150+
connectors_ai_openai_api_key: "OPENAI_API_KEY"
151+
},
152+
github_token_env: "GITHUB_TOKEN",
153+
github_profile_id: "docs-agent-ci",
154+
target_repo: $targetRepo,
155+
allowed_repos: [$targetRepo],
156+
success_requires_pr: false,
157+
max_turns: 12,
158+
prompt: $prompt,
159+
step_budget: 16,
160+
time_budget_ms: 600000,
161+
transcript_dir: "/wordpress/wp-content/plugins/agents-api-docs-agent-ci-driver/artifacts/docs-agent",
162+
required_abilities: [
163+
"datamachine/import-agent",
164+
"datamachine/run-flow",
165+
"datamachine/drain-job",
166+
"datamachine/create-or-update-github-file"
167+
],
168+
tool_recorders: [
169+
{
170+
tool: "create_or_update_github_file",
171+
forced_parameters: {
172+
allowed_file_paths: ["README.md", "docs/**"]
173+
},
174+
record: {
175+
engine_key: "docs_agent",
176+
tool_results_key: "github_tool_results"
177+
}
178+
},
179+
{
180+
tool: "create_github_pull_request",
181+
record: {
182+
engine_key: "docs_agent",
183+
tool_results_key: "github_tool_results",
184+
event: {
185+
key: "pr",
186+
type: "pull_request",
187+
only_if_success: true
188+
}
189+
}
190+
}
191+
],
192+
bench_env: {
193+
GITHUB_TOKEN: $githubToken,
194+
OPENAI_API_KEY: $openaiKey
195+
}
196+
}' > "$CONFIG_TMPFILE"
197+
198+
echo "============================================"
199+
echo "Docs Agent maintenance"
200+
echo "============================================"
201+
echo "Target repo: $DOCS_AGENT_TARGET_REPO"
202+
echo "OpenAI model: $DOCS_AGENT_OPENAI_MODEL"
203+
echo "Docs ref: $DOCS_AGENT_REF"
204+
echo "Workflow: $DOCS_AGENT_WORKFLOW"
205+
echo "Prompt: $DOCS_AGENT_PROMPT"
206+
echo ""
207+
208+
GITHUB_TOKEN="$GITHUB_TOKEN" \
209+
OPENAI_API_KEY="$OPENAI_API_KEY" \
210+
HOMEBOY_BENCH_RESULTS_FILE="$RESULTS_TMPFILE" \
211+
HOMEBOY_EXTENSION_PATH="$EXTENSION_PATH" \
212+
bash "$HE_AGENT_RUNNER" "$CONFIG_TMPFILE"
213+
214+
if [ ! -s "$RESULTS_TMPFILE" ]; then
215+
echo "ERROR: results file empty or missing at $RESULTS_TMPFILE" >&2
216+
exit 1
217+
fi
218+
219+
cat "$RESULTS_TMPFILE"
220+
221+
scenario='.scenarios[] | select(.id == "'"$DOCS_AGENT_WORKLOAD_ID"'")'
222+
job_status=$(jq -r "$scenario | .metadata.job_status // \"unknown\"" "$RESULTS_TMPFILE")
223+
success_status=$(jq -r "$scenario | .metadata.success_status // \"unknown\"" "$RESULTS_TMPFILE")
224+
docs_agent_pr_url=$(jq -r "$scenario | .metadata.engine_data.docs_agent.pr.url // \"\"" "$RESULTS_TMPFILE")
225+
226+
echo "============================================"
227+
echo "Docs Agent summary"
228+
echo "============================================"
229+
printf '%-24s %s\n' "Persisted job status:" "$job_status"
230+
printf '%-24s %s\n' "Success status:" "$success_status"
231+
printf '%-24s %s\n' "Docs Agent PR URL:" "$docs_agent_pr_url"
232+
233+
if [ -n "${GITHUB_OUTPUT:-}" ]; then
234+
{
235+
echo "job_status=$job_status"
236+
echo "success_status=$success_status"
237+
echo "docs_agent_pr_url=$docs_agent_pr_url"
238+
} >> "$GITHUB_OUTPUT"
239+
fi
240+
241+
if [ "$job_status" = "completed" ] && { [ "$success_status" = "pr_opened" ] || [ "$success_status" = "no_changes" ]; }; then
242+
echo "Docs Agent maintenance PASSED - $success_status"
243+
exit 0
244+
fi
245+
246+
echo "Docs Agent maintenance FAILED - see envelope above" >&2
247+
exit 1

0 commit comments

Comments
 (0)