Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
cb2a2f7
Revise supported frameworks and protocols sections
NathanTarbert Oct 31, 2025
a136965
Update image and enhance README formatting
NathanTarbert Nov 3, 2025
168a380
Add workflow to autoapprove community PRs (#636)
maxkorp Nov 5, 2025
54f5c41
Addressing regression in ADK 0.3.2 (#626)
contextablemark Nov 5, 2025
fba25db
0.0.40 (#632)
mme Nov 6, 2025
1857c0a
fix(langgraph): handle Command tool output (#639)
xdave Nov 6, 2025
913c18b
make sidebar nav maintain query string params (#649)
maxkorp Nov 6, 2025
4a2627a
ag-ui support claude agent python sdk
Nov 7, 2025
b698e5b
Merge remote-tracking branch 'origin/main'
Nov 7, 2025
970c2db
fix: dump safe json whenever string is required in lg-python fastapi …
ranst91 Nov 7, 2025
079169d
feature: implement claude agent sdk typescript version
Nov 7, 2025
a3c0fe1
chore(docs): Add the frameworks, protocols, and clients section in th…
NathanTarbert Nov 7, 2025
e7df7c6
fix: fix claude code agent sdk protocal transform error
Nov 8, 2025
05a3ec1
feature: finish claude agent sdk ts middleware
Nov 8, 2025
5c57b10
Merge branch 'main' of https://github.com/ag-ui-protocol/ag-ui
Nov 8, 2025
c98f5dd
chore: remove outdated ADK Middleware implementation documentation an…
Nov 9, 2025
c57eb1e
chore: update example environment file for Claude Agent SDK by removi…
Nov 10, 2025
c26363f
chore: update .gitignore to include all .env.local files and remove b…
Nov 10, 2025
8b19f36
chore: add .gitignore to prevent future .env.local commits
Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions .github/workflows/auto-approve-community.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
name: Auto-approve community PRs

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
pull-requests: write
contents: read

jobs:
auto-approve:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetch PR branch
run: |
git fetch origin ${{ github.event.pull_request.head.ref }}:${{ github.event.pull_request.head.ref }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Auto-approve based on CODEOWNERS
env:
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
node << 'EOF'
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

const prAuthor = process.env.PR_AUTHOR;
const prNumber = process.env.PR_NUMBER;

// Get changed files
const changedFiles = execSync(
`git diff --name-only origin/${process.env.BASE_REF}...origin/${process.env.HEAD_REF}`,
{ encoding: 'utf-8' }
)
.trim()
.split('\n')
.filter(f => f.trim());

console.log(`Changed files (${changedFiles.length}):`);
changedFiles.forEach(f => console.log(` - ${f}`));

// Parse CODEOWNERS file
const codeownersPath = '.github/CODEOWNERS';
const codeownersContent = fs.readFileSync(codeownersPath, 'utf-8');
const lines = codeownersContent.split('\n');

// Map of path patterns to owners (excluding root * rule)
const codeownersRules = [];

for (const line of lines) {
const trimmed = line.trim();
// Skip empty lines and comments
if (!trimmed || trimmed.startsWith('#')) {
continue;
}

// Skip root * line
if (trimmed.startsWith('* ')) {
console.log('Skipping root * rule');
continue;
}

// Parse pattern and owners
const parts = trimmed.split(/\s+/);
if (parts.length < 2) {
continue;
}

const pattern = parts[0];
const owners = parts.slice(1).map(o => o.replace('@', ''));

codeownersRules.push({ pattern, owners });
}

console.log('\nCODEOWNERS rules (excluding root):');
codeownersRules.forEach(rule => {
console.log(` ${rule.pattern} -> ${rule.owners.join(', ')}`);
});

// Function to check if a file matches a CODEOWNERS pattern
// CODEOWNERS patterns match:
// - Exact file/directory path
// - pattern/ matches everything in that directory
// - pattern/** matches everything recursively in that directory
function matchesPattern(file, pattern) {
// Normalize paths (handle both / and \ separators)
const normalizePath = (p) => p.replace(/\\/g, '/');
const normalizedFile = normalizePath(file);
const normalizedPattern = normalizePath(pattern);

// Exact match
if (normalizedFile === normalizedPattern) {
return true;
}

// Pattern ends with /**: matches recursively in directory
if (normalizedPattern.endsWith('/**')) {
const dirPrefix = normalizedPattern.slice(0, -3);
return normalizedFile.startsWith(dirPrefix + '/');
}

// Pattern ends with /: matches everything in directory
if (normalizedPattern.endsWith('/')) {
const dirPrefix = normalizedPattern.slice(0, -1);
return normalizedFile.startsWith(dirPrefix + '/');
}

// Pattern is a directory prefix (matches subdirectories)
if (normalizedFile.startsWith(normalizedPattern + '/')) {
return true;
}

return false;
}

// Check each changed file
// CODEOWNERS rules are evaluated top-to-bottom, first match wins
const unapprovedFiles = [];

for (const file of changedFiles) {
let matched = false;
let owned = false;

// Find the first matching rule (CODEOWNERS uses first match semantics)
for (const rule of codeownersRules) {
if (matchesPattern(file, rule.pattern)) {
matched = true;
// First match wins in CODEOWNERS, so check ownership here
owned = rule.owners.includes(prAuthor);
break; // Stop at first match
}
}

// File must be matched by a non-root CODEOWNERS rule AND author must own it
if (!matched || !owned) {
unapprovedFiles.push(file);
}
}

// Decision
if (unapprovedFiles.length === 0) {
console.log(`\n✅ All changed files are owned by ${prAuthor} according to CODEOWNERS`);

// Check if already approved by this workflow
try {
const reviews = JSON.parse(
execSync(`gh pr view ${prNumber} --json reviews`, { encoding: 'utf-8' })
);

// Check if there's already an approval from GitHub Actions bot
// (look for approval with the auto-approve message)
const hasAutoApproval = reviews.reviews.some(
review => review.state === 'APPROVED' &&
review.body &&
review.body.includes('Auto-approved: PR author has CODEOWNERS access')
);

if (hasAutoApproval) {
console.log('PR already auto-approved by this workflow');
} else {
// Approve the PR using GitHub Actions bot account
execSync(
`gh pr review ${prNumber} --approve --body "Auto-approved: PR author ${prAuthor} has CODEOWNERS access to all changed files (excluding root rule)"`,
{ stdio: 'inherit' }
);
console.log(`PR approved automatically for ${prAuthor}`);
}
} catch (error) {
console.error('Error checking/approving PR:', error.message);
// Don't fail the workflow if approval fails (might already be approved, etc.)
console.log('Continuing despite approval error...');
}
} else {
console.log(`\n❌ Not auto-approved: Some files are not owned by ${prAuthor}`);
console.log('Unauthorized files:');
unapprovedFiles.forEach(f => console.log(` - ${f}`));
}
EOF
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,11 @@ node_modules
.vscode

**/mastra.db*

.pnpm-store

**/.poetry-cache
**/.env.local
integrations/claude-agent-sdk/**/.env.local
**/pnpm-lock.yaml
pnpm-lock.yaml
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pnpm dev
# Run linting
pnpm lint


# Run type checking
pnpm check-types

Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ Built for simplicity and flexibility, it enables seamless integration between AI

<a href="https://discord.gg/Jd3FzfdJa8" target="_blank"> Join our Discord → </a> &nbsp;&nbsp;&nbsp; <a href="https://ag-ui.com/" target="_blank"> Read the Docs → </a> &nbsp;&nbsp;&nbsp; <a href="https://dojo.ag-ui.com/" target="_blank"> Go to the AG-UI Dojo → </a> &nbsp;&nbsp;&nbsp; <a href="https://x.com/CopilotKit" target="_blank"> Follow us → </a>

<img width="4096" height="1752" alt="Your application-AG-UI protocol" src="https://github.com/user-attachments/assets/dc58c64c-3257-490a-b827-e163475f4166" />
<img width="4096" height="1752" alt="Your application-AG-UI protocol" src="https://github.com/user-attachments/assets/0ecc3a63-7947-442f-9a6e-be887d0bf245" />



## 🚀 Getting Started
Create a new AG-UI application in seconds:
Expand Down Expand Up @@ -75,7 +77,7 @@ AG-UI is complementary to the other 2 top agentic protocols
- 🧑‍💻 Human-in-the-loop collaboration


## 🛠 Supported Frameworks
## 🛠 Supported Integrations

AG-UI was born from CopilotKit's initial partnership with LangGraph and CrewAI - and brings the incredibly popular agent-user-interactivity infrastructure to the wider agentic ecosystem.

Expand All @@ -89,15 +91,15 @@ AG-UI was born from CopilotKit's initial partnership with LangGraph and CrewAI -
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [LangGraph](https://www.langchain.com/langgraph) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/langgraph/) 🎮 [Demos](https://dojo.ag-ui.com/langgraph-fastapi/feature/shared_state) |
| [Google ADK](https://google.github.io/adk-docs/get-started/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/adk) 🎮 [Demos](https://dojo.ag-ui.com/adk-middleware) |
| [Google ADK](https://google.github.io/adk-docs/get-started/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/adk) 🎮 [Demos](https://dojo.ag-ui.com/adk-middleware/feature/shared_state?openCopilot=true) |
| [CrewAI](https://crewai.com/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/crewai-flows) 🎮 [Demos](https://dojo.ag-ui.com/crewai/feature/shared_state) |

#### 🧩 1st Party
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [Mastra](https://mastra.ai/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/mastra/) 🎮 [Demos](https://dojo.ag-ui.com/mastra) |
| [Mastra](https://mastra.ai/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/mastra/) 🎮 [Demos](https://dojo.ag-ui.com/mastra/feature/tool_based_generative_ui) |
| [Pydantic AI](https://github.com/pydantic/pydantic-ai) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/pydantic-ai/) 🎮 [Demos](https://dojo.ag-ui.com/pydantic-ai/feature/shared_state) |
| [Agno](https://github.com/agno-agi/agno) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/agno/) 🎮 [Demos](https://dojo.ag-ui.com/agno) |
| [Agno](https://github.com/agno-agi/agno) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/agno/) 🎮 [Demos](https://dojo.ag-ui.com/agno/feature/tool_based_generative_ui) |
| [LlamaIndex](https://github.com/run-llama/llama_index) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/llamaindex/) 🎮 [Demos](https://dojo.ag-ui.com/llamaindex/feature/shared_state) |
| [AG2](https://ag2.ai/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/ag2/) |
| [AWS Bedrock Agents](https://aws.amazon.com/bedrock/agents/) | 🛠️ In Progress | – |
Expand All @@ -112,7 +114,7 @@ AG-UI was born from CopilotKit's initial partnership with LangGraph and CrewAI -
| [Cloudflare Agents](https://developers.cloudflare.com/agents/) | 🛠️ In Progress | – |


## Protocols
## Agent Interaction Protocols

| Protocols | Status | AG-UI Resources | Integrations |
| ---------- | ------- | ---------------- | ------------- |
Expand Down
Loading