From agentic-skills
Scheduled triage agent for Google Jules coding sessions. Polls the Jules API for completed sessions (from agents like Bolt, Palette, and one-off code reviews), analyzes their changeSets, and determines which should be promoted to GitHub PRs. Supports configurable autonomy modes (full, approve-high-risk, approve-all) and per-agent configuration. Works across multiple GitHub orgs and repos. Once a session is promoted, hands off to github-babysitter pr-care for merge management. Also handles AWAITING_USER_FEEDBACK sessions that need confirmation. Designed to run daily on a schedule but can also be invoked on-demand. Use this skill when the user mentions Jules triage, Jules review triage, Jules session management, promoting Jules reviews to PRs, daily Jules digest, scheduling Jules review processing, Bolt sessions, Palette sessions, or managing Jules agents across repos.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agentic-skills:jules-wranglerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A scheduled triage agent that bridges Google Jules coding sessions with your GitHub PR workflow.
A scheduled triage agent that bridges Google Jules coding sessions with your GitHub PR workflow.
Jules operates asynchronously — it performs code reviews, generates fixes, and produces plans independently from your main GitHub workflow. This skill closes the loop by:
# On-demand — triage all pending Jules sessions now
"Triage my Jules sessions"
# Scheduled — set up daily triage at 9am
"Schedule Jules triage daily at 9am"
# Specific repo — only triage sessions for a given repo
"Triage Jules sessions for owner/repo"
# Digest only — just show me what's pending without acting
"Show me a Jules session digest"
The skill reads .jules-wrangler.yml from the repo root or global config, then falls back to legacy .jules-triage.yml. If absent, it uses sensible defaults.
Read references/config-schema.md for the full schema. Key sections:
# .jules-wrangler.yml
autonomy: approve-high-risk # full | approve-high-risk | approve-all
schedule: "0 9 * * *" # cron expression for scheduled runs
repositories: # repos to monitor (empty = all)
- owner/repo-a
- owner/repo-b
promotion_criteria:
min_confidence: 0.7 # minimum triage confidence to auto-promote
require_tests_pass: true # only promote if Jules' tests passed
max_files_changed: 50 # skip mega-sessions, flag for manual review
categories: # which session types to consider
- bug_fix
- code_review
- performance
- security
github_babysitter:
enabled: true # hand off promoted PRs to github-babysitter pr-care
config_path: .github-babysitter.yml
notifications:
slack_channel: "" # optional Slack notification channel
digest_format: summary # summary | detailed | minimal
The skill requires a Jules API key. It looks for credentials in this order:
JULES_API_KEY.env file: in the repo root or workspace rootjules_api_key field in .jules-wrangler.yml or legacy .jules-triage.ymlAPI keys are managed at https://jules.google.com/settings (max 3 keys per account).
All API calls use the header: X-Goog-Api-Key: <your-key>
Base URL: https://jules.googleapis.com/v1alpha
Query the Jules API to find sessions requiring triage:
curl 'https://jules.googleapis.com/v1alpha/sessions?pageSize=100' \
-H 'X-Goog-Api-Key: $JULES_API_KEY'
Sessions progress through these states:
| State | Meaning | Triage Action |
|---|---|---|
ACTIVE | Still running | Skip — check next cycle |
AWAITING_PLAN_APPROVAL | Plan ready, needs approval | Review plan, approve or reject |
AWAITING_USER_FEEDBACK | Jules needs input | Flag for human attention |
COMPLETED | Work finished successfully | Primary triage target |
FAILED | Session errored | Log failure, skip |
On each triage run:
COMPLETED and AWAITING_PLAN_APPROVAL statesSessions use the format sourceContext.source = "sources/github/{org}/{repo}".
If repositories is configured, parse the source string and match against configured repos. Note that repos may exist under multiple orgs (e.g., darksheer/Acheron and darksheer-labs/Acheron). Match by {org}/{repo} pair.
# Example source values observed:
# "sources/github/darksheer-labs/ARC"
# "sources/github/darksheer-labs/Acheron"
# "sources/github/darksheer/Acheron"
# "sources/github/darksheer/ft3"
The sourceContext.githubRepoContext.startingBranch field indicates which branch the session targets.
For each session requiring triage, gather full context:
curl 'https://jules.googleapis.com/v1alpha/sessions/{SESSION_ID}/activities' \
-H 'X-Goog-Api-Key: $JULES_API_KEY'
Activities contain the session's full history. Each activity has id, name,
createTime, and originator fields, plus one or more event payload fields:
planGenerated: Jules created a work plan (contains plan.steps[] with title and description)planApproved: Plan was approved (contains planId)agentMessaged: Jules sent a message (contains agentMessage text — often asking for confirmation)progressUpdated: Human-readable progress message for an execution stepartifacts: Opaque progress/output metadata, often paired with progressUpdatedsessionCompleted: Completion marker for finished sessions"user")Sessions in AWAITING_USER_FEEDBACK fall into two categories:
Bolt/Palette agents asking for approval before finalizing:
In full autonomy mode, auto-respond with: "Looks good, please finalize and submit."
Jules asking clarifying questions before it can proceed — these need real answers:
These are the highest-value triage targets. An unanswered question blocks the entire session.
When the skill encounters a substantive question, it can:
gh)POST /sessions/{id}:sendMessage| Mode | Behavior |
|---|---|
full | Auto-answer questions using codebase analysis. Send response directly. |
approve-high-risk | Draft an answer, present to user for approval before sending. Auto-answer simple confirmations. |
approve-all | Surface the question in the digest. Never auto-respond. |
For each question Jules asks:
.editorconfig, lint configs, CLAUDE.md, existing patterns)sendMessage APISafety guardrails:
Jules asks: "Should I remove the unused before parameter from _write_report?"
Skill analysis:
src/acheron/intel_draft_finalizer.pybefore is truly unused (_ = before pattern)before argument?Response sent to Jules:
Yes, please remove the `before` parameter entirely. It's unused (just assigned to `_`)
and the callers will be cleaner without it. Also yes, group the remaining parameters
into a dataclass — `ReportContext` would be a good name. Keep `summary` and
`missing_items` as explicit kwargs since they're the primary outputs.
From the activities, extract:
AUTO_CREATE_PR outputs, or does it need manual PR creation?Assign a triage score (0.0–1.0) based on:
| Factor | Weight | Signal |
|---|---|---|
| Tests pass | 0.30 | Jules ran tests and they passed |
| Scope appropriate | 0.20 | Files changed within max_files_changed threshold |
| Clear intent | 0.15 | Session prompt was specific and well-defined |
| Category match | 0.15 | Matches configured categories |
| No errors | 0.10 | No failures or retries during execution |
| Plan approval | 0.10 | Plan was reviewed (manual or auto) |
Sessions scoring >= min_confidence are candidates for promotion.
fullAuto-promote all sessions scoring above min_confidence. Create PRs immediately and hand off to github-babysitter pr-care. No human input required.
approve-high-riskAuto-promote sessions that are:
Require approval for:
approve-allNever auto-promote. Generate the daily digest with recommendations and wait for explicit human approval before creating any PRs.
Automatically reject (never promote) sessions that:
When a session is approved for promotion:
Sessions produce two output types in session.outputs[]:
changeSet — always present when work was done:
{
"changeSet": {
"source": "sources/github/darksheer-labs/ARC",
"gitPatch": {
"unidiffPatch": "diff --git a/...",
"baseCommitId": "a9aae35a2608...",
"suggestedCommitMessage": "⚡ Bolt: Optimize timeline bucketing..."
}
}
}
pullRequest — only present if Jules auto-created a PR:
{
"pullRequest": {
"url": "https://github.com/darksheer-labs/ARC/pull/281",
"title": "⚡ Bolt: [performance improvement] optimize timeline bucketing",
"description": "...",
"baseRef": "main",
"headRef": "bolt-timeline-map-lookup-10409236580371261383"
}
}
Many sessions have only changeSet without pullRequest, so the triage skill
must be able to promote patches manually. Do not assume the current percentage
is stable; report the observed counts in each digest.
The PR already exists. The skill:
session.outputs[].pullRequest.urlThe skill creates a PR from the patch:
gitPatch.unidiffPatch for the diffgitPatch.baseCommitIdgitPatch.suggestedCommitMessage (first line)session.url)jules-wrangler, agent name label (e.g., bolt, palette)Once the PR exists, invoke github-babysitter pr-care with:
"Review PR #{number} on {owner}/{repo} — promoted from Jules session"
GitHub Babysitter takes over from here: running PR care, triaging review and CI findings, preparing fixes, and managing merge readiness.
After each triage run, generate a structured digest:
# Jules Wrangler Digest — {date}
## Summary
- Sessions scanned: {total}
- Promoted to PR: {promoted_count}
- Awaiting approval: {pending_count}
- Rejected: {rejected_count}
- Still active (skipped): {active_count}
## Promoted Sessions
| Session | Repo | Category | Score | PR |
|---------|------|----------|-------|-----|
| {title} | {repo} | {cat} | {score} | #{pr_number} |
## Awaiting Your Approval
| Session | Repo | Category | Score | Risk |
|---------|------|----------|-------|------|
| {title} | {repo} | {cat} | {score} | {risk_reason} |
## Rejected
| Session | Repo | Reason |
|---------|------|--------|
| {title} | {repo} | {rejection_reason} |
If notifications.slack_channel is configured, post the digest there. Otherwise, output locally or post as a GitHub issue on a designated tracking repo.
Track outcomes to improve triage over time:
Per session:
Per category:
Over time, adjust:
min_confidence threshold based on actual merge ratesUse the /schedule skill to set up daily runs (e.g., "Schedule jules-wrangler daily at 9am"). Manual invocation also works: "Triage my Jules sessions now" or "Triage Jules session {session_id} specifically".
Read references/jules-api.md for complete endpoint documentation, request patterns, and response shapes.
| File | When to Read |
|---|---|
references/jules-api.md | When making Jules API calls or debugging responses |
references/config-schema.md | When parsing or generating .jules-wrangler.yml or migrating .jules-triage.yml |
references/triage-scoring.md | When evaluating session quality or tuning thresholds |
references/promotion-workflow.md | When creating PRs from sessions or handing off |
references/digest-template.md | When generating the daily report |
Schedule Trigger (or manual invocation)
│
├─ 1. Load config, authenticate with Jules API
├─ 2. List sessions, filter to triage-eligible states
│
├─ 3. AWAITING_USER_FEEDBACK sessions (unblock first):
│ ├─ Read last agentMessaged activity
│ ├─ Classify: simple confirmation vs. substantive question
│ ├─ Simple → auto-respond "finalize and submit" (full mode)
│ ├─ Substantive → analyze codebase, formulate answer
│ ├─ Send response via sendMessage API (or defer to digest)
│ └─ Session resumes → will appear as COMPLETED next cycle
│
├─ 4. COMPLETED sessions (promote):
│ ├─ Retrieve activities and outputs
│ ├─ Score the session (tests, scope, intent, category)
│ ├─ Apply autonomy rules
│ └─ Decision: promote / request approval / reject
│
├─ 5. For promoted sessions:
│ ├─ Create PR (if not already created by Jules)
│ └─ Hand off to github-babysitter pr-care
│
├─ 6. Generate daily digest
├─ 7. Post notifications (Slack, GitHub issue, local)
└─ 8. Record learning data
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub darksheer/agentic-skills --plugin agentic-skills