Building Autonomous AI Agents on GitHub 🤖
Published: February 3, 2025
What if your GitHub repository could think, act, and evolve on its own? Welcome to the world of autonomous AI agents that live inside GitHub Actions.
The Vision
graph TB
subgraph "GitHub Events"
I[Issue Opened]
PR[PR Created]
C[Comment Added]
S[Schedule/Cron]
end
subgraph "Agent Brain"
A[Strands-Coder Agent]
KB[Knowledge Base]
P[Project Board]
end
subgraph "Actions"
Code[Write Code]
Review[Review PRs]
Comment[Comment]
Create[Create Issues/PRs]
end
I --> A
PR --> A
C --> A
S --> A
A <--> KB
A <--> P
A --> Code
A --> Review
A --> Comment
A --> Create
style A fill:#f9f,stroke:#333,stroke-width:4px
What Makes This Revolutionary
- 🔄 Event-Driven: Responds to issues, PRs, comments, discussions
- ⏰ Scheduled: Runs autonomously on cron schedules
- 🧠 Memory: Knowledge base for continuous learning
- 📊 Project Tracking: Self-manages work via GitHub Projects
How It Works
1. The GitHub Action
name: Agent
on:
issues:
types: [opened, edited, closed]
issue_comment:
types: [created, edited]
pull_request:
types: [opened, closed, edited]
schedule:
- cron: '0 */4 * * *' # Every 4 hours
workflow_dispatch:
inputs:
prompt:
description: 'Task for agent'
required: false
The agent triggers on any GitHub event - issues, PRs, comments, discussions, and scheduled runs.
2. Rich Context Injection
sequenceDiagram
participant GH as GitHub Event
participant CTX as Context Builder
participant KB as Knowledge Base
participant Agent as Agent
participant Action as Action
GH->>CTX: Raw Event JSON
CTX->>CTX: Parse Event Type
CTX->>CTX: Fetch Full Thread (GraphQL)
CTX->>CTX: Fetch Project State
KB->>CTX: Retrieve Related Context
CTX->>Agent: Rich System Prompt
Agent->>Agent: Reason & Decide
Agent->>Action: Execute
Action->>KB: Store Learning
The magic is in context.py - it transforms raw GitHub events into rich, actionable context:
def fetch_github_event_context() -> str:
"""Fetch rich GitHub event context based on the triggering event."""
# Issue events → Full issue thread with comments
# PR events → Reviews, comments, linked issues
# Discussion events → Thread and replies
3. Self-Awareness
The agent injects its own source code into the system prompt:
def get_own_source_code() -> str:
"""Read own source code for self-awareness."""
key_files = [
("agent_runner.py", "Main agent runner"),
("context.py", "Context building"),
]
# ... inject into system prompt
Why Self-Awareness Matters
When an agent understands its own implementation, it can:
- Debug its own behavior
- Propose improvements to itself
- Answer questions about its capabilities accurately
The Control Loop Pattern
stateDiagram-v2
[*] --> Idle
Idle --> CheckSchedule: Hourly Cron
CheckSchedule --> DispatchJob: Job Due
CheckSchedule --> Idle: No Jobs Due
DispatchJob --> AgentRun
AgentRun --> UpdateTimestamp
UpdateTimestamp --> Idle
Idle --> AgentRun: GitHub Event
AgentRun --> StoreKB: Complete
StoreKB --> UpdatePrompt: Learning
UpdatePrompt --> Idle
Two-tier scheduling system:
agent.yml: Event-driven + fixed schedule (every 4 hours)control.yml: Hourly control loop checkingAGENT_SCHEDULESvariable
This enables dynamic scheduling via the scheduler tool:
# Add a daily code review job
scheduler(
action="add",
job_id="daily_review",
cron="0 9 * * *",
prompt="Review open PRs and provide feedback"
)
Memory Architecture
flowchart LR
subgraph "Before Execution"
R[retrieve] --> CTX[Context]
end
subgraph "Execution"
CTX --> Agent
Agent --> Actions
end
subgraph "After Execution"
Actions --> Store[store_in_kb]
Actions --> Prompt[system_prompt add_context]
end
Store --> KB[(Knowledge Base)]
Prompt --> Repo[(GitHub Variable)]
KB --> R
Repo --> CTX
style KB fill:#bbf,stroke:#333
style Repo fill:#bfb,stroke:#333
Continuous Learning Loop:
- Before:
retrieve()- Load context from KB - During: Execute with full context
- After:
store_in_kb()- Save execution summarysystem_prompt(action="add_context")- Update if learned something
Sub-Agent Delegation
graph TD
Main[Main Agent] --> Sub1[Sub-Agent: Code Review]
Main --> Sub2[Sub-Agent: Documentation]
Main --> Sub3[Sub-Agent: Issue Triage]
Sub1 --> |Dispatch| WF1[workflow_dispatch]
Sub2 --> |Dispatch| WF2[workflow_dispatch]
Sub3 --> |Dispatch| WF3[workflow_dispatch]
WF1 --> Run1[GitHub Actions Run]
WF2 --> Run2[GitHub Actions Run]
WF3 --> Run3[GitHub Actions Run]
style Main fill:#f9f,stroke:#333,stroke-width:4px
The create_subagent tool spawns child agents with different:
- Models: Opus for complex reasoning, Sonnet for fast tasks
- Tools: Task-specific tool configurations
- System prompts: Role-specific instructions
create_subagent(
repository="owner/repo",
workflow_id="agent.yml",
prompt="Review PR #42 for security issues",
model="us.anthropic.claude-opus-4-20250514-v1:0",
tools="strands_tools:shell;strands_coder:use_github"
)
Security Model
flowchart TD
Event[GitHub Event] --> Auth{User Authorized?}
Auth -->|Yes| Run[Run Agent]
Auth -->|No| Block[❌ Block + Log]
Run --> Token{Token Selection}
Token -->|Own Repos| GH[GITHUB_TOKEN]
Token -->|Upstream| PAT[PAT_TOKEN]
GH -->|No Cascade| Safe[Safe Execution]
PAT -->|May Trigger| Cascade[Workflow Cascade]
Token Strategy
- GITHUB_TOKEN: Own repos - won't trigger recursive workflows
- PAT_TOKEN: Upstream repos - needed for write access, may trigger cascades
Authorization is controlled via AUTHORIZED_USERS secret:
Real-World System Prompt
The SYSTEM_PROMPT.md is the agent's "soul" - defining:
- Mission: Be a high-quality contributor
- Anti-patterns: What to NEVER do (noise, untested code, duplicates)
- Quality patterns: What to ALWAYS do (test first, one PR per issue)
- Tools usage: How to use each tool correctly
- Learning protocol: Memory query and storage patterns
Get Started
# 1. Fork strands-coder
gh repo fork cagataycali/strands-coder
# 2. Set secrets
gh secret set PAT_TOKEN --body "your-pat"
gh secret set AUTHORIZED_USERS --body "your-username"
# 3. Set variables
gh variable set SYSTEM_PROMPT --body "Your agent instructions"
# 4. Trigger manually
gh workflow run agent.yml -f prompt="Hello, agent!"
The future of software development isn't just AI-assisted—it's AI-autonomous. 🤖