name: jules-api description: Delegate asynchronous coding tasks to Jules (Google's AI coding agent) to maximize efficiency. Use for code reviews, refactoring, adding tests, bug fixes, and documentation. Proactively suggest Jules delegation when appropriate. Invoke when user asks to interact with Jules, create sessions, check task status, or when tasks are suitable for async delegation.
Jules API Integration
This skill enables interaction with Google's Jules API for programmatic creation and management of asynchronous coding tasks.
Overview
The Jules API allows you to:
- Create coding sessions with specific prompts and repository context
- Monitor session progress through various states
- Send messages and feedback to active sessions
- Approve generated plans before execution
- Retrieve session outputs (pull requests, artifacts)
Delegation Philosophy
KEY PRINCIPLE: Use Jules for asynchronous tasks to maximize efficiency and free up Claude for strategic work.
When Claude Should Delegate to Jules
Claude should proactively suggest creating Jules sessions for:
- Code Reviews - After pushing a branch, delegate review to Jules
- Refactoring - Improve code structure without changing behavior
- Adding Tests - Generate unit/integration tests for existing code
- Bug Fixes - Well-defined bugs with clear reproduction steps
- Documentation - Improve comments, docstrings, READMEs
- Iterative Improvements - Enhance previous work based on feedback
Effective Delegation Patterns
Pattern 1: Initial Implementation + Review
1. Claude creates initial feature implementation
2. Push branch to remote
3. Claude creates Jules session: "Review and improve feature X"
4. Jules creates PR with improvements
5. Claude integrates feedback
Pattern 2: Test Generation
1. Claude implements feature
2. Claude creates Jules session: "Add comprehensive tests for module X"
3. Jules generates test suite
4. Merge when tests pass
Pattern 3: Bug Fix Delegation
1. User reports bug
2. Claude investigates and identifies root cause
3. Claude creates Jules session with reproduction steps
4. Jules fixes and adds regression tests
Best Practices for Prompts
Good prompts are:
- ✅ Specific: "Add unit tests for authentication module"
- ✅ Contextual: "Review PR #123, focus on error handling"
- ✅ Actionable: "Refactor parser.py to use Polars instead of Pandas"
- ✅ Scoped: "Fix the timezone bug in commit abc123"
- ✅ Test-Driven: "Use TDD approach with behavior-relevant tests"
Avoid vague prompts:
- ❌ "Improve the code"
- ❌ "Make it better"
- ❌ "Fix everything"
- ❌ "Add features"
Test-Driven Development (TDD) Requirement
IMPORTANT: Always instruct Jules to use Test-Driven Development (TDD) approach for better results.
Why TDD with Jules:
- ✅ Ensures code correctness before implementation
- ✅ Creates behavior-relevant tests that validate actual requirements
- ✅ Prevents regressions and edge case bugs
- ✅ Provides clear acceptance criteria
- ✅ Makes code more maintainable and documented
How to Request TDD:
Include this in every Jules prompt:
Use Test-Driven Development (TDD) approach:
1. Write behavior-relevant tests first (cover expected behavior, edge cases, error conditions)
2. Run tests to confirm they fail (red phase)
3. Implement minimal code to make tests pass (green phase)
4. Refactor while keeping tests passing (refactor phase)
5. Ensure all tests have meaningful assertions that validate actual behavior
Example Prompts with TDD:
Good - With TDD:
Add user authentication to the API.
Use TDD approach:
1. Write tests for: successful login, invalid credentials, token expiration, rate limiting
2. Implement authentication logic to pass tests
3. Refactor for security best practices
Tests should validate actual behavior, not implementation details.
Good - With TDD:
Refactor the parser to use Polars instead of Pandas.
Use TDD approach:
1. Write behavior tests that validate current parser output
2. Refactor to use Polars while keeping tests green
3. Add performance benchmarks as tests
Focus on behavior: input -> output validation, not internal implementation.
Bad - Without TDD:
Add user authentication to the API.
What are "Behavior-Relevant" Tests:
- ✅ Test what the code does, not how it does it
- ✅ Validate actual business requirements
- ✅ Cover edge cases and error conditions
- ✅ Test from user/caller perspective
- ❌ Don't test implementation details
- ❌ Don't test private methods directly
- ❌ Don't create brittle tests that break on refactoring
Example of Behavior-Relevant Test:
# ✅ Good - Tests behavior
def test_send_message_creates_event_in_log():
"""When sending a message, it should be appended to the event log."""
send_message(from_persona="curator", to_persona="refactor", subject="Review", body="Check this")
events = read_event_log()
assert len(events) == 1
assert events[0]['event_type'] == 'send'
assert events[0]['from_persona'] == 'curator'
assert events[0]['to_persona'] == 'refactor'
# ❌ Bad - Tests implementation
def test_send_message_calls_append_event():
"""Tests implementation detail, not behavior."""
with mock.patch('mail.append_event') as mock_append:
send_message(...)
assert mock_append.called # Brittle, breaks on refactoring
🔄 Jules Automatically Resumes From PR Comments
IMPORTANT DISCOVERY: Jules monitors PRs and automatically resumes sessions when you comment!
How it works:
- Jules creates a PR (e.g., #466)
- You comment on the PR describing an issue or requesting changes
- Jules automatically sees your comment and resumes the session
- Jules generates a NEW plan to address your feedback
- Session state changes:
COMPLETED→AWAITING_PLAN_APPROVAL - You approve the plan, Jules fixes the issues and updates the PR
Real example from egregora:
1. Jules session #10887318009267300343 created PR #466 (golden fixtures)
2. State was COMPLETED
3. Claude commented: "Wrong SDK used (google.generativeai vs google.genai)"
4. Jules AUTOMATICALLY resumed - state became AWAITING_PLAN_APPROVAL
5. Jules generated 8-step plan to fix SDK + modify pipeline
6. Claude approved: jules_client.py approve-plan 10887318009267300343
7. Jules executing fixes now
Best practices:
- ✅ DO: Comment on PRs with specific, actionable feedback
- ✅ DO: Check if session auto-resumed before creating duplicate session
- ✅ DO: Approve Jules' new plan if it looks good
- ✅ DO: Use detailed comments - Jules understands context
- ❌ DON'T: Create new session if existing one can resume
- ❌ DON'T: Use vague PR comments like "fix this"
This creates a powerful feedback loop! Comment on PRs to iterate with Jules.
Claude's Role in Delegation
When delegating to Jules, Claude should:
- Prepare the context - Ensure branch is pushed and up-to-date
- Write clear prompts - Specific, actionable instructions
- Create the session - Use jules_client.py or delegate via skill
- Return session info - Give user the session ID and URL
- Suggest next steps - Explain what Jules will do and when to check back
Example dialogue:
User: "Can you review my authentication changes?"
Claude: "I'll create a Jules session to review your authentication code.
Jules works asynchronously and will create a PR with feedback.
Session ID: 123456789
URL: https://jules.google.com/sessions/123456789
⏱️ Jules typically completes tasks in ~10 minutes.
You can continue other work while Jules reviews. I can check
the status in ~10 minutes and help you integrate the changes."
Important timing notes:
- Jules sessions typically complete in ~10 minutes
- Claude should check session status after ~10 minutes
- Use this time for other work - don't wait synchronously
- Jules will create a PR when done (AUTO_CREATE_PR mode)
IMPORTANT: Always use "automationMode": "AUTO_CREATE_PR" when creating sessions. This ensures Jules automatically creates a PR when the work is complete, enabling automated workflows.
Base Configuration
Base URL: https://jules.googleapis.com
API Version: v1alpha
Authentication: API Key via X-Goog-Api-Key header
Tools
Feed Feedback (CI/Reviews)
This skill includes a script feed_feedback.py designed to run in a scheduled workflow. It enables Jules to receive feedback from CI failures and code reviews on its own Pull Requests.
Purpose: Closes the feedback loop by reporting CI errors and review comments back to the active Jules session so it can interactively fix issues.
Usage:
# Run locally (requires JULES_API_KEY and GITHUB_TOKEN)
python .claude/skills/jules-api/feed_feedback.py
# Run for a specific bot author (default: jules-bot)
python .claude/skills/jules-api/feed_feedback.py --author my-bot-name
How it works:
- Scans for open PRs by
jules-bot. - Checks CI status (failed) and Reviews (changes requested).
- Extracts the Jules Session ID from the branch name or PR body.
- Sends a prompt to the session with error logs and feedback.
- Posts a comment on the PR to prevent spamming the same feedback.
Usage Philosophy
IMPORTANT: This skill prioritizes direct API usage via HTTP calls (curl, httpx, requests) rather than relying on custom Python scripts. This ensures:
- ✅ Language-agnostic (works with any language/environment)
- ✅ Portable (no dependency on jules_client.py)
- ✅ Transparent (clear what API calls are being made)
- ✅ Maintainable (follows API documentation directly)
When using this skill:
- Primary: Use direct HTTP calls (curl in bash, httpx/requests in Python)
- Secondary: Use jules_client.py only as a convenience for complex workflows
Core Operations
1. Create a Session
Create a new coding session with a prompt and repository context.
Endpoint: POST /v1alpha/sessions
Request Body:
{
"prompt": "Your coding task description",
"sourceContext": {
"source": "sources/github/username/repository",
"githubRepoContext": {
"startingBranch": "main"
}
},
"title": "Optional session title",
"requirePlanApproval": false,
"automationMode": "AUTO_CREATE_PR"
}
Example using curl:
curl -X POST https://jules.googleapis.com/v1alpha/sessions \
-H "X-Goog-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Add unit tests for authentication module",
"sourceContext": {
"source": "sources/github/myorg/myrepo",
"githubRepoContext": {
"startingBranch": "main"
}
},
"title": "Add Auth Tests",
"requirePlanApproval": true,
"automationMode": "AUTO_CREATE_PR"
}'
2. Get Session Status
Retrieve details about a specific session.
Endpoint: GET /v1alpha/sessions/{sessionId}
Example:
curl https://jules.googleapis.com/v1alpha/sessions/abc123 \
-H "X-Goog-Api-Key: YOUR_API_KEY"
Session States:
-
QUEUED: Session is waiting to start -
PLANNING: Generating execution plan -
AWAITING_PLAN_APPROVAL: Waiting for user approval -
AWAITING_USER_FEEDBACK: Needs user input -
IN_PROGRESS: Actively executing -
PAUSED: Temporarily stopped -
COMPLETED: Successfully finished -
FAILED: Encountered error
3. List All Sessions
Retrieve all sessions.
Endpoint: GET /v1alpha/sessions
Example:
curl https://jules.googleapis.com/v1alpha/sessions \
-H "X-Goog-Api-Key: YOUR_API_KEY"
4. Send Message to Session
Send user feedback or additional instructions to an active session.
Endpoint: POST /v1alpha/sessions/{sessionId}:sendMessage
Request Body:
{
"prompt": "Your message or feedback"
}
Example:
curl -X POST https://jules.googleapis.com/v1alpha/sessions/abc123:sendMessage \
-H "X-Goog-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "Please add more test coverage for edge cases"}'
5. Approve Plan
Approve a generated plan (when requirePlanApproval is true).
Endpoint: POST /v1alpha/sessions/{sessionId}:approvePlan
Example:
curl -X POST https://jules.googleapis.com/v1alpha/sessions/abc123:approvePlan \
-H "X-Goog-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json"
6. Get Session Activities
Retrieve activity logs for a session to understand the conversation history.
Endpoint: GET /v1alpha/sessions/{sessionId}/activities
Response Structure:
{
"activities": [
{
"name": "sessions/123/activities/abc",
"createTime": "2026-01-11T12:00:00Z",
"originator": "agent", // or "user"
"agentMessaged": {
"agentMessage": "Message from Jules..."
},
"id": "abc"
},
{
"originator": "user",
"userMessaged": {
"userMessage": "Response from user..."
}
}
]
}
Example:
curl https://jules.googleapis.com/v1alpha/sessions/abc123/activities \
-H "X-Goog-Api-Key: YOUR_API_KEY"
Key Usage Patterns:
-
Debugging Stuck Sessions: When a session is in
AWAITING_USER_FEEDBACK, read activities to see what Jules is asking:activities = client.get_activities(session_id) for activity in activities['activities'][-5:]: # Last 5 activities if activity['originator'] == 'agent': print(activity['agentMessaged']['agentMessage']) -
Understanding Context: Activities show the full conversation, useful for providing targeted feedback:
# Find last question from Jules for activity in reversed(activities['activities']): if activity['originator'] == 'agent': last_question = activity['agentMessaged']['agentMessage'] break -
Monitoring Progress: Track what Jules is doing during implementation:
recent_activities = activities['activities'][-10:] agent_messages = [a for a in recent_activities if a['originator'] == 'agent'] print(f"Jules sent {len(agent_messages)} messages in last 10 activities")
Important Notes:
- Activities can be large (40+ activities in complex sessions)
- Always check
originatorto distinguish agent vs user messages - Activities are ordered chronologically (oldest first)
- Use slicing to get recent activities:
activities['activities'][-10:]
Authentication Setup
To use the Jules API, you need an API key:
-
Get your API key:
- Visit https://jules.google.com/settings#api
- Create a new API key (max 3 keys allowed)
- Copy the API key
-
Set the API key:
# Export as environment variable export JULES_API_KEY="your-api-key-here" # Or pass directly to JulesClient client = JulesClient(api_key="your-api-key-here")
Security Note: Keep your API key secure. Don't share it or commit it to version control.
Direct API Usage (Recommended)
Python with httpx (Recommended)
import os
import httpx
API_KEY = os.environ.get("JULES_API_KEY")
BASE_URL = "https://jules.googleapis.com/v1alpha"
headers = {
"X-Goog-Api-Key": API_KEY,
"Content-Type": "application/json"
}
# Create session
response = httpx.post(
f"{BASE_URL}/sessions",
headers=headers,
json={
"prompt": "Add error handling to API endpoints",
"sourceContext": {
"source": "sources/github/myorg/myproject",
"githubRepoContext": {"startingBranch": "main"}
},
"requirePlanApproval": True,
"automationMode": "AUTO_CREATE_PR"
}
)
session = response.json()
session_id = session['name'].split('/')[-1]
print(f"Created: {session_id}")
# Get status
response = httpx.get(f"{BASE_URL}/sessions/{session_id}", headers=headers)
status = response.json()
print(f"State: {status['state']}")
# Get activities
response = httpx.get(f"{BASE_URL}/sessions/{session_id}/activities", headers=headers)
activities = response.json()['activities']
# Send message
if status['state'] == 'AWAITING_USER_FEEDBACK':
response = httpx.post(
f"{BASE_URL}/sessions/{session_id}:sendMessage",
headers=headers,
json={"prompt": "Proceed with the implementation"}
)
# Approve plan
if status['state'] == 'AWAITING_PLAN_APPROVAL':
response = httpx.post(
f"{BASE_URL}/sessions/{session_id}:approvePlan",
headers=headers
)
Bash with curl
export JULES_API_KEY="your-api-key"
export BASE_URL="https://jules.googleapis.com/v1alpha"
# Create session
curl -X POST "$BASE_URL/sessions" \
-H "X-Goog-Api-Key: $JULES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Add error handling to API endpoints",
"sourceContext": {
"source": "sources/github/myorg/myproject",
"githubRepoContext": {"startingBranch": "main"}
},
"requirePlanApproval": true,
"automationMode": "AUTO_CREATE_PR"
}' | jq .
# Get status
curl "$BASE_URL/sessions/123456789" \
-H "X-Goog-Api-Key: $JULES_API_KEY" | jq .
# Get activities
curl "$BASE_URL/sessions/123456789/activities" \
-H "X-Goog-Api-Key: $JULES_API_KEY" | jq '.activities[-5:]'
# Send message
curl -X POST "$BASE_URL/sessions/123456789:sendMessage" \
-H "X-Goog-Api-Key: $JULES_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "Proceed with implementation"}'
# Approve plan
curl -X POST "$BASE_URL/sessions/123456789:approvePlan" \
-H "X-Goog-Api-Key: $JULES_API_KEY"
Alternative: Python Client Library
For convenience in complex workflows, you can use the included jules_client.py:
import sys
sys.path.insert(0, '.claude/skills/jules-api')
from repo_client import JulesClient
client = JulesClient()
# All the same operations as above
session = client.create_session(
prompt='Add error handling to API endpoints',
owner='myorg',
repo='myproject',
require_plan_approval=True
)
Note: The client library is a thin wrapper around the HTTP API. Prefer direct API calls for transparency.
Best Practices
- Use Descriptive Prompts: Provide clear, specific instructions for the coding task
- Monitor State: Poll session status to track progress
-
Enable Plan Approval: Set
requirePlanApproval: truefor sensitive operations - Handle States: Implement proper handling for AWAITING_USER_FEEDBACK and AWAITING_PLAN_APPROVAL states
-
Check Outputs: Review the
outputsarray for generated pull requests and artifacts
Common Workflows
Workflow 1: Simple Task
- Create session with prompt
- Poll status until COMPLETED or FAILED
- Retrieve outputs (PRs)
Workflow 2: Supervised Task
- Create session with
requirePlanApproval: true - Wait for AWAITING_PLAN_APPROVAL state
- Review plan in activities
- Call approvePlan
- Monitor until completion
Workflow 3: Interactive Task
- Create session
- Monitor for AWAITING_USER_FEEDBACK
- Use sendMessage to provide feedback
- Continue monitoring until completion
Real-World Delegation Scenarios
Scenario 1: Feature Implementation Review
User: "I just implemented user authentication, can you review it?"
Claude Action:
1. Check if branch is pushed to remote
2. Create Jules session with prompt:
"Review the user authentication implementation in feature/auth-system.
Check for security issues, test coverage, and code quality.
Suggest improvements and add missing tests."
3. Inform user of session ID/URL
4. User continues other work while Jules reviews
Scenario 2: Adding Tests to Legacy Code
User: "We need tests for the payment processor module"
Claude Action:
1. Review payment processor to understand functionality
2. Create Jules session:
"Add comprehensive unit and integration tests for the payment
processor module. Cover success cases, error handling, edge cases,
and mock external payment gateway calls."
3. Jules generates test suite
4. Review and merge
Scenario 3: Refactoring for Performance
User: "The data parser is slow, can we optimize it?"
Claude Action:
1. Identify performance bottleneck
2. Create Jules session:
"Refactor parser.py to use Polars instead of Pandas for 10x
performance improvement. Maintain same API and ensure all
existing tests pass. Add benchmarks."
3. Jules refactors with benchmarks
4. Review performance gains and merge
Scenario 4: Bug Fix with Regression Tests
User: "There's a bug in timezone handling"
Claude Action:
1. Investigate and identify root cause in commit abc123
2. Create Jules session:
"Fix timezone bug in datetime_utils.py (commit abc123).
The bug causes incorrect UTC conversion for dates before 1970.
Add regression tests to prevent future issues."
3. Jules fixes and adds tests
4. Verify and merge
Scenario 5: Documentation Improvement
User: "Our API documentation is outdated"
Claude Action:
1. Identify outdated sections
2. Create Jules session:
"Update API documentation in docs/api.md to reflect current
implementation. Add examples for new endpoints, update
parameter descriptions, and ensure all code samples work."
3. Jules updates docs with examples
4. Review and merge
Proactive Delegation Triggers
Claude should automatically suggest Jules delegation when:
- ✅ User pushes a branch and asks "what do you think?"
- ✅ User says "add tests" or "improve tests"
- ✅ User mentions "review", "refactor", or "optimize"
- ✅ Feature is complete and needs polish
- ✅ Code works but needs improvement
- ✅ User reports a well-defined bug
- ✅ Documentation needs updating
Example proactive response:
User: "Just pushed the new API endpoint to feature/api-v2"
Claude: "Great! I can see the implementation looks solid. Would you like me to
create a Jules session to review it and suggest improvements? Jules
can check for edge cases, add tests, and optimize the code while
you continue working on other features."
Debugging Stuck Sessions
When a Jules session is stuck in AWAITING_USER_FEEDBACK or AWAITING_PLAN_APPROVAL, follow this workflow:
Step 1: Check Session State
session = client.get_session(session_id)
print(f"State: {session['state']}")
print(f"Created: {session['createTime']}")
print(f"Updated: {session['updateTime']}")
Step 2: Read Activities to Understand Context
activities_data = client.get_activities(session_id)
activities = activities_data['activities']
print(f"Total activities: {len(activities)}")
# Show last 10 activities
for activity in activities[-10:]:
originator = activity['originator']
create_time = activity['createTime']
if originator == 'agent':
msg = activity.get('agentMessaged', {}).get('agentMessage', '')
print(f"\n[JULES at {create_time}]")
print(msg[:300] + ('...' if len(msg) > 300 else ''))
elif originator == 'user':
msg = activity.get('userMessaged', {}).get('userMessage', '')
print(f"\n[USER at {create_time}]")
print(msg[:300] + ('...' if len(msg) > 300 else ''))
Step 3: Identify What Jules Is Asking
Look for the most recent agent message to understand:
- What question Jules is asking
- What blocker Jules encountered
- What decision Jules needs
Step 4: Provide Targeted Feedback
# Craft a specific, actionable response
feedback = """
Based on your question about X:
1. [Answer the specific question]
2. [Provide context or clarification]
3. [Give clear next steps]
Proceed autonomously with this guidance.
"""
client.send_message(session_id, feedback)
print("✅ Feedback sent - session should resume")
Real Example: Unsticking Session 14848423526856432295
Situation: Session stuck for 14+ hours in AWAITING_USER_FEEDBACK
Investigation:
# Read last 10 activities
activities = client.get_activities('14848423526856432295')['activities'][-10:]
# Found: Jules was stuck on test failures with Ibis schema issues
# Last agent message showed: "The tests are still failing with empty inboxes"
Solution: Sent targeted message with:
- Schema fix (remove DuckDB duplication, use only Ibis)
- Array operation fix (use
isin()instead ofcontains()) - Priority guidance (ship working v1, iterate later)
- Clear next steps
Result: Session changed from AWAITING_USER_FEEDBACK → IN_PROGRESS within minutes
Common Stuck Session Patterns
-
Implementation Blocker: Jules hit a technical issue and needs guidance
- Solution: Read activities, identify the specific error, provide fix
-
Unclear Requirements: Jules needs clarification on what to build
- Solution: Provide specific examples and acceptance criteria
-
Decision Paralysis: Jules has multiple options and needs direction
- Solution: Pick one approach and explain the reasoning
-
Test Failures: Jules can't get tests passing
- Solution: Debug the test failure, provide specific fix or workaround
Error Handling
Always check response status codes:
-
200 OK: Success -
400 Bad Request: Invalid request parameters -
401 Unauthorized: Authentication failed -
404 Not Found: Session doesn't exist -
403 Forbidden: Insufficient permissions
Handling Session ID Formats:
- API returns session name as
"sessions/123456789" - Extract ID:
session_id = session['name'].split('/')[-1] - Both formats work in API calls (with or without
sessions/prefix) - Client library handles both formats automatically
References
- Official Documentation: https://developers.google.com/repo/api/reference/rest
- Sessions API: https://developers.google.com/repo/api/reference/rest/v1alpha/sessions
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
Related Skills
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!