Documentation Index Fetch the complete documentation index at: https://docs.abv.dev/llms.txt
Use this file to discover all available pages before exploring further.
How GitHub Integration Works
Configure ABV webhooks
Set up webhooks in your ABV project to send events when prompts are created, updated, or deleted. ABV sends HTTP POST requests to your specified endpoint with full prompt data. Webhook configuration:
Navigate to Prompts > Webhooks in ABV
Create a webhook with your target endpoint
Choose events to trigger (created, updated, deleted)
Optionally filter by prompt labels or tags
ABV sends webhook payloads containing: {
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"timestamp" : "2024-07-10T10:30:00Z" ,
"type" : "prompt-version" ,
"action" : "created" ,
"prompt" : {
"name" : "movie-critic" ,
"version" : 3 ,
"labels" : [ "production" ],
"prompt" : "..."
}
}
Set up GitHub Actions or webhook server
Choose one of two integration patterns based on your needs: Option 1: GitHub Actions (recommended for most users)
No infrastructure required
Uses GitHubβs repository_dispatch events
Perfect for triggering CI/CD workflows
Limited to GitHub-hosted workflows
Option 2: Webhook Server (for advanced use cases)
Requires hosting a webhook receiver
Syncs prompts to git repository as commits
Provides full git history for prompts
Can trigger additional automation beyond GitHub
Both options can be combined for maximum automation.
Automate testing and deployment
Once webhooks reach GitHub, configure workflows to:
Run automated tests on prompt changes
Validate prompt syntax and structure
Deploy prompts to staging/production environments
Notify teams via Slack or email
Create pull requests for review
Example workflow trigger: on :
repository_dispatch :
types : [ abv-prompt-update ]
Access prompt data in workflows via github.event.client_payload.* to make deployment decisions.
Track versions in git history
If using the webhook server option, every prompt change creates a git commit: commit abc123def456
Author: ABV Webhook < webhook@abv.de v >
Date: 2024-07-10 10:30:00
created: movie-critic v3
diff --git a/abv_prompt.json b/abv_prompt.json
+ "version": 3,
+ "prompt": "As a {{criticLevel}} movie critic..."
This provides a complete audit trail and enables git-based workflows (diff, blame, revert).
Integration Patterns
GitHub Actions with repository_dispatch (No Infrastructure)
The simplest integration pattern. Trigger GitHub Actions workflows directly from ABV webhooks without hosting any infrastructure. How it works:
ABV webhook sends POST to https://api.github.com/repos/{owner}/{repo}/dispatches
GitHub dispatches a repository_dispatch event to your repo
GitHub Actions workflow triggers on this event type
Workflow runs tests, deployments, or any automation
Benefits:
Zero infrastructure required
GitHub-managed reliability
Native integration with Actions ecosystem
Secrets managed in GitHub
Limitations:
Doesnβt create git commits (no history tracking)
Limited to GitHub Actions workflows
Canβt sync prompts to repository files
Best for: Teams that want automated deployments without managing infrastructure, and donβt need git history for prompts.
Webhook Server for Prompt Sync (Full Git History)
Host a webhook receiver that commits prompt changes to your git repository, providing full version control history. How it works:
ABV webhook sends POST to your hosted endpoint (e.g., https://your-server.com/webhook/prompt)
Webhook server receives payload and parses prompt data
Server commits prompt content to repository file (e.g., abv_prompt.json)
Git commit triggers normal CI/CD workflows (if configured)
Benefits:
Full git history for prompts (diff, blame, revert)
Prompts version-controlled alongside code
Can trigger multiple automation systems
Complete audit trail in repository
Limitations:
Requires hosting webhook server (Render, Fly.io, Heroku, etc.)
Additional infrastructure to maintain
Need GitHub PAT for API access
Best for: Teams that want prompts fully integrated into version control, or need comprehensive audit trails.
Combined Approach (Actions + Sync)
Use both patterns together for maximum automation and visibility. How it works:
Set up webhook server to sync prompts to git (creates history)
Git commits trigger GitHub Actions workflows (via standard on: push)
Workflows run tests and deployments based on git changes
All prompt changes visible in repository history
Benefits:
Git history for prompts
Automated CI/CD via GitHub Actions
Pull request reviews for prompt changes
Comprehensive automation and audit trail
Setup:
Deploy webhook server for git sync
Configure standard GitHub Actions on push events
Prompts flow: ABV β Webhook Server β Git Commit β GitHub Actions β Deployment
Best for: Enterprise teams requiring both automation and compliance/audit capabilities.
Secure your GitHub integration to prevent unauthorized access and ensure data integrity. Verify webhook signatures: import hmac
import hashlib
def verify_signature ( payload_body : bytes , signature : str , secret : str ) -> bool :
"""Verify ABV webhook signature using signing secret."""
expected = hmac.new(
secret.encode(),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest( f "sha256= { expected } " , signature)
# In your webhook handler:
signature = request.headers.get( "x-abv-signature" )
if not verify_signature(request.body, signature, SIGNING_SECRET ):
raise HTTPException( status_code = 401 , detail = "Invalid signature" )
Limit GitHub PAT scope:
Use fine-grained PATs restricted to specific repositories
For repository_dispatch: actions: read and write
For git commits: contents: read and write, metadata: read-only
Never use classic tokens with full repo scope unless absolutely necessary
Environment variables:
Store GitHub tokens in environment variables or secrets managers
Never commit tokens to repositories
Rotate tokens periodically
Handle retries safely:
ABV retries failed webhooks with exponential backoff
Design webhook handlers to be idempotent (duplicate events safe)
Return 2xx status codes on success to prevent retries
Implementation: GitHub Actions (No Infrastructure)
Step 1: Create GitHub Actions Workflow
Create .github/workflows/abv-ci.yml in your repository: name : ABV Prompt CI
on :
repository_dispatch :
types : [ abv-prompt-update ]
workflow_dispatch : # Allow manual triggers
jobs :
test :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- name : Display prompt info
run : |
echo "Action: ${{ github.event.client_payload.action }}"
echo "Prompt: ${{ github.event.client_payload.prompt.name }}"
echo "Version: ${{ github.event.client_payload.prompt.version }}"
echo "Labels: ${{ github.event.client_payload.prompt.labels }}"
- name : Run tests
run : |
# Add your test commands
npm test
# or: python -m pytest
deploy :
needs : test
runs-on : ubuntu-latest
# Only deploy prompts labeled "production"
if : contains(github.event.client_payload.prompt.labels, 'production')
steps :
- uses : actions/checkout@v4
- name : Deploy to production
run : |
echo "Deploying ${{ github.event.client_payload.prompt.name }} v${{ github.event.client_payload.prompt.version }}"
# Your deployment commands
# ./deploy.sh
- name : Notify team
run : |
echo "Deployed prompt: ${{ github.event.client_payload.prompt.name }} v${{ github.event.client_payload.prompt.version }}"
# Send Slack notification, etc.
Accessing webhook data:
Use github.event.client_payload.* to access prompt data
github.event.client_payload.action: created, updated, or deleted
github.event.client_payload.prompt.*: Full prompt object (name, version, labels, content, etc.)
Conditional execution:
Use if: contains(github.event.client_payload.prompt.labels, 'production') to run steps only for production prompts
Use if: github.event.client_payload.action == 'created' to run on prompt creation only
Step 2: Create GitHub Token for Actions
Generate a GitHub Personal Access Token with appropriate permissions. Token creation steps:
Go to GitHub Settings β Developer settings β Personal access tokens
Click Generate new token
Choose token type and set permissions:
Token Type Required Permissions Personal Access Token (classic) repo scope (for private repos) or public_repo scope (for public repos)Fine-grained PAT Repository permissions: Actions : read and write, Metadata : read-only GitHub App Repository permissions: Actions : read and write
Generate token and copy it immediately (wonβt be shown again)
Store token securely for ABV webhook configuration
Security tip: Fine-grained PATs are recommended as they can be scoped to specific repositories and have expiration dates.
Step 3: Configure ABV Webhook for GitHub Actions
Step 4: Test GitHub Actions Integration
Verify the integration works end-to-end. Testing steps:
Update a prompt in ABV:
Open an existing prompt or create a new one
Make a change (edit content, update variables, etc.)
Assign the production label
Save the prompt (creates a new version)
Check GitHub Actions tab:
Navigate to your repository on GitHub
Click Actions tab
Look for a new workflow run named βABV Prompt CIβ
Workflow should show βrepository_dispatchβ as trigger
Verify workflow execution:
Click into the workflow run
Verify test job completes successfully
Verify deploy job runs (if prompt had production label)
Check job logs to see prompt data (name, version, labels)
Troubleshooting:
If workflow doesnβt trigger: verify webhook URL and GitHub token
If workflow fails: check logs for errors
If deploy job skipped: verify prompt has production label
Expected result: Prompt change in ABV automatically triggers GitHub Actions workflow, runs tests, and deploys (if conditions met).
Implementation: Webhook Server (Git Sync)
The webhook server receives prompt change events from ABV and commits them to your GitHub repository. Flow diagram: Workflow:
User saves prompt in ABV
ABV sends webhook POST to your server
Server validates webhook signature
Server fetches current file SHA from GitHub
Server commits updated prompt JSON to repository
Git commit triggers standard CI/CD workflows
Components:
ABV Webhook: Sends prompt change events
Webhook Server: FastAPI application (or any language/framework)
GitHub API: Receives commits via REST API
Repository: Stores prompts in version control
Step 1: Configure ABV Webhook for Sync
Step 2: Prepare GitHub Repository and Token
Set up GitHub repository and create a PAT for API access. Create .env file with configuration:# GitHub credentials
GITHUB_TOKEN = ghp_your_github_pat_here
GITHUB_REPO_OWNER = your-username-or-org
GITHUB_REPO_NAME = your-repo-name
# Optional configurations
GITHUB_FILE_PATH = abv_prompt.json # File to store prompts
GITHUB_BRANCH = main # Target branch
REQUIRED_LABEL = production # Only sync prompts with this label (empty = sync all)
GitHub PAT permissions:
Create a token with minimal required permissions:Permission Type Required Scopes Fine-grained PAT (recommended) Repository permissions: β’ Contents : Read and write β’ Metadata : Read-only Classic PAT β’ public_repo (for public repositories) β’ repo (for private repositories)
PAT creation:
GitHub Settings β Developer settings β Personal access tokens
Generate new token (fine-grained recommended)
Select repository access (specific repo or all repos)
Set permissions as listed above
Generate and copy token
Add to .env file as GITHUB_TOKEN
Security: Fine-grained PATs expire and can be scoped to specific repositories, reducing security risk.
Step 3: Implement FastAPI Webhook Server
Create a webhook server that receives ABV events and commits to GitHub. Create main.py: from typing import Any, Dict
from uuid import UUID
import json
import base64
import httpx
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from fastapi import FastAPI, HTTPException, Body
class GitHubSettings ( BaseSettings ):
"""GitHub repository configuration."""
GITHUB_TOKEN : str
GITHUB_REPO_OWNER : str
GITHUB_REPO_NAME : str
GITHUB_FILE_PATH : str = "abv_prompt.json"
GITHUB_BRANCH : str = "main"
REQUIRED_LABEL : str = "" # Optional: only sync prompts with this label
model_config = SettingsConfigDict(
env_file = ".env" ,
env_file_encoding = "utf-8" ,
case_sensitive = True
)
config = GitHubSettings()
class ABVEvent ( BaseModel ):
"""ABV webhook event structure."""
id : UUID = Field( description = "Event identifier" )
timestamp: str = Field( description = "Event timestamp" )
type : str = Field( description = "Event type" )
action: str = Field( description = "Performed action" )
prompt: Dict[ str , Any] = Field( description = "Prompt content" )
async def sync ( event : ABVEvent) -> Dict[ str , Any]:
"""Synchronize prompt data to GitHub repository."""
# Check if prompt has required label (if specified)
if config. REQUIRED_LABEL :
prompt_labels = event.prompt.get( "labels" , [])
if config. REQUIRED_LABEL not in prompt_labels:
return { "skipped" : f "Prompt does not have required label ' { config. REQUIRED_LABEL } '" }
api_endpoint = f "https://api.github.com/repos/ { config. GITHUB_REPO_OWNER } / { config. GITHUB_REPO_NAME } /contents/ { config. GITHUB_FILE_PATH } "
request_headers = {
"Authorization" : f "Bearer { config. GITHUB_TOKEN } " ,
"Accept" : "application/vnd.github.v3+json"
}
content_json = json.dumps(event.prompt, indent = 2 )
encoded_content = base64.b64encode(content_json.encode( "utf-8" )).decode( "utf-8" )
name = event.prompt.get( "name" , "unnamed" )
version = event.prompt.get( "version" , "unknown" )
message = f " { event.action } : { name } v { version } "
payload = {
"message" : message,
"content" : encoded_content,
"branch" : config. GITHUB_BRANCH
}
async with httpx.AsyncClient() as http_client:
try :
existing = await http_client.get(api_endpoint, headers = request_headers, params = { "ref" : config. GITHUB_BRANCH })
if existing.status_code == 200 :
payload[ "sha" ] = existing.json().get( "sha" )
except Exception :
pass
try :
response = await http_client.put(api_endpoint, headers = request_headers, json = payload)
response.raise_for_status()
return response.json()
except Exception as e:
raise HTTPException( status_code = 500 , detail = f "Repository sync failed: { str (e) } " )
app = FastAPI( title = "ABV GitHub Sync" , version = "1.0" )
@app.post ( "/webhook/prompt" , status_code = 201 )
async def receive_webhook ( event : ABVEvent = Body( ... )):
"""Process ABV webhook and sync to GitHub."""
result = await sync(event)
return {
"status" : "synced" ,
"commit_info" : result.get( "commit" , {}),
"file_info" : result.get( "content" , {})
}
@app.get ( "/status" )
async def health_status ():
"""Service health check."""
return { "healthy" : True }
How it works:
Validates webhook payload structure using Pydantic
Checks if prompt has required label (if configured)
Fetches existing file SHA from GitHub (required for updates)
Commits prompt JSON to repository with descriptive message
Returns commit info to ABV (2xx status prevents retries)
Install dependencies: pip install fastapi uvicorn pydantic-settings httpx
Run locally: uvicorn main:app --reload --port 8000
Access health check at http://localhost:8000/status. Local testing: Use ngrok or similar to expose localhost for webhook testing:ngrok http 8000
# Use ngrok URL in ABV webhook configuration
Step 4: Deploy Webhook Server
Deploy the webhook server to a public HTTPS endpoint. Deployment options: Option 1: Render.com (recommended for beginners)
Create requirements.txt:
fastapi
uvicorn[standard]
pydantic-settings
httpx
Create render.yaml:
services :
- type : web
name : abv-github-sync
env : python
buildCommand : pip install -r requirements.txt
startCommand : uvicorn main:app --host 0.0.0.0 --port $PORT
envVars :
- key : GITHUB_TOKEN
sync : false
- key : GITHUB_REPO_OWNER
sync : false
- key : GITHUB_REPO_NAME
sync : false
Push to GitHub and connect repository in Render dashboard
Set environment variables in Render dashboard
Deploy
Option 2: Fly.io
Install Fly CLI: curl -L https://fly.io/install.sh | sh
Run fly launch and follow prompts
Set secrets: fly secrets set GITHUB_TOKEN=... GITHUB_REPO_OWNER=... GITHUB_REPO_NAME=...
Deploy: fly deploy
Option 3: Heroku
Create Procfile:
web: uvicorn main:app --host 0.0.0.0 --port $PORT
Deploy via Heroku CLI or GitHub integration
Set config vars in Heroku dashboard
After deployment:
Note your public HTTPS URL (e.g., https://abv-sync.onrender.com)
Update ABV webhook endpoint to https://your-domain.com/webhook/prompt
Test by updating a prompt in ABV
Verify new commit appears in GitHub repository
Testing and Troubleshooting
Verify the webhook server is working correctly. Test health endpoint: curl https://your-domain.com/status
# Should return: {"healthy": true}
Test webhook endpoint manually: curl -X POST https://your-domain.com/webhook/prompt \
-H "Content-Type: application/json" \
-d '{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-07-10T10:30:00Z",
"type": "prompt-version",
"action": "created",
"prompt": {
"name": "test-prompt",
"version": 1,
"labels": ["production"],
"prompt": "Test prompt content",
"type": "text"
}
}'
Expected response: {
"status" : "synced" ,
"commit_info" : { ... },
"file_info" : { ... }
}
Check GitHub repository:
Navigate to your repository
Look for new commit with message: created: test-prompt v1
Verify abv_prompt.json contains the prompt data
Common issues: Issue Solution 401 Unauthorized Verify GitHub token has correct permissions 404 Not Found Check GITHUB_REPO_OWNER and GITHUB_REPO_NAME are correct 409 Conflict File SHA mismatch; ensure server fetches current SHA No commit created Check server logs for errors; verify token has contents: write permission ABV shows failed webhooks Ensure server returns 2xx status code; check server logs
View server logs:
Render: Dashboard β Logs tab
Fly.io: fly logs
Heroku: heroku logs --tail
Advanced Patterns
Filter by Label (Production Only)
Sync only prompts with specific labels (e.g., production) to avoid cluttering git history with experiments. In webhook server .env: REQUIRED_LABEL = production
Behavior:
Prompts with production label: synced to GitHub
Prompts without production label: skipped (webhook returns success without committing)
In GitHub Actions: # Only deploy production-labeled prompts
if : contains(github.event.client_payload.prompt.labels, 'production')
This pattern ensures only vetted, production-ready prompts trigger deployments or appear in git history.
Store different prompts in separate files for better organization. Modify webhook server to use prompt name as file path: # Instead of fixed GITHUB_FILE_PATH
file_path = f "prompts/ { event.prompt[ 'name' ] } .json"
api_endpoint = f "https://api.github.com/repos/ { config. GITHUB_REPO_OWNER } / { config. GITHUB_REPO_NAME } /contents/ { file_path } "
Result: prompts/
movie-critic.json
customer-support.json
billing-assistant.json
Each prompt gets its own file, making git diffs clearer and enabling granular access control.
Trigger Multiple Workflows
Trigger different workflows based on prompt metadata (labels, tags, name patterns). GitHub Actions with conditional workflows: name : ABV Prompt Workflows
on :
repository_dispatch :
types : [ abv-prompt-update ]
jobs :
deploy-production :
if : contains(github.event.client_payload.prompt.labels, 'production')
runs-on : ubuntu-latest
steps :
- name : Deploy to production
run : ./deploy-prod.sh
deploy-staging :
if : contains(github.event.client_payload.prompt.labels, 'staging')
runs-on : ubuntu-latest
steps :
- name : Deploy to staging
run : ./deploy-staging.sh
run-experiments :
if : contains(github.event.client_payload.prompt.tags, 'experiment')
runs-on : ubuntu-latest
steps :
- name : Run A/B test
run : ./run-ab-test.sh
Use cases:
Deploy production-labeled prompts to production environment
Deploy staging-labeled prompts to staging environment
Run experiments for prompts tagged with experiment
Signature Verification for Security
Verify webhook signatures to ensure requests come from ABV and havenβt been tampered with. Add to webhook server: import hmac
import hashlib
from fastapi import Header, HTTPException, Request
SIGNING_SECRET = "your-signing-secret-from-abv"
def verify_signature ( payload_body : bytes , signature : str ) -> bool :
"""Verify ABV webhook signature."""
expected = hmac.new(
SIGNING_SECRET .encode(),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest( f "sha256= { expected } " , signature)
@app.post ( "/webhook/prompt" , status_code = 201 )
async def receive_webhook (
request : Request,
event : ABVEvent = Body( ... ),
x_abv_signature : str = Header( ... )
):
"""Process ABV webhook with signature verification."""
body = await request.body()
if not verify_signature(body, x_abv_signature):
raise HTTPException( status_code = 401 , detail = "Invalid signature" )
result = await sync(event)
return { "status" : "synced" , "commit_info" : result.get( "commit" , {})}
Benefits:
Prevents unauthorized webhook calls
Ensures payload integrity (not modified in transit)
Production security best practice
Next Steps
Webhook & Slack Integration Send prompt change notifications to Slack channels using webhooks
Get Started with Prompt Management Complete quickstart guide for creating and deploying prompts
Version Control Deploy and rollback prompts safely using labels and versions
A/B Testing Prompts Run statistical A/B tests on prompt variants in production