> ## 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.

# GitHub Integration for ABV Prompts

> Automate prompt deployments, trigger CI/CD workflows, and version control prompts in GitHub using ABV webhooks and GitHub Actions.

# How GitHub Integration Works

<Steps>
  <Step title="Configure ABV webhooks" icon="webhook">
    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:

    ```json theme={null}
    {
      "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": "..."
      }
    }
    ```
  </Step>

  <Step title="Set up GitHub Actions or webhook server" icon="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.
  </Step>

  <Step title="Automate testing and deployment" icon="rocket">
    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:**

    ```yaml theme={null}
    on:
      repository_dispatch:
        types: [abv-prompt-update]
    ```

    Access prompt data in workflows via `github.event.client_payload.*` to make deployment decisions.
  </Step>

  <Step title="Track versions in git history" icon="code-commit">
    If using the webhook server option, every prompt change creates a git commit:

    ```bash theme={null}
    commit abc123def456
    Author: ABV Webhook <webhook@abv.dev>
    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).
  </Step>
</Steps>

# Integration Patterns

<AccordionGroup>
  <Accordion title="GitHub Actions with repository_dispatch (No Infrastructure)" icon="bolt">
    The simplest integration pattern. Trigger GitHub Actions workflows directly from ABV webhooks without hosting any infrastructure.

    **How it works:**

    1. ABV webhook sends POST to `https://api.github.com/repos/{owner}/{repo}/dispatches`
    2. GitHub dispatches a `repository_dispatch` event to your repo
    3. GitHub Actions workflow triggers on this event type
    4. 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.
  </Accordion>

  <Accordion title="Webhook Server for Prompt Sync (Full Git History)" icon="server">
    Host a webhook receiver that commits prompt changes to your git repository, providing full version control history.

    **How it works:**

    1. ABV webhook sends POST to your hosted endpoint (e.g., `https://your-server.com/webhook/prompt`)
    2. Webhook server receives payload and parses prompt data
    3. Server commits prompt content to repository file (e.g., `abv_prompt.json`)
    4. 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.
  </Accordion>

  <Accordion title="Combined Approach (Actions + Sync)" icon="arrows-split-up-and-left">
    Use both patterns together for maximum automation and visibility.

    **How it works:**

    1. Set up webhook server to sync prompts to git (creates history)
    2. Git commits trigger GitHub Actions workflows (via standard `on: push`)
    3. Workflows run tests and deployments based on git changes
    4. 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.
  </Accordion>

  <Accordion title="Security Best Practices" icon="shield-check">
    Secure your GitHub integration to prevent unauthorized access and ensure data integrity.

    **Verify webhook signatures:**

    ```python theme={null}
    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
  </Accordion>
</AccordionGroup>

# Implementation: GitHub Actions (No Infrastructure)

<AccordionGroup>
  <Accordion title="Step 1: Create GitHub Actions Workflow" icon="file-code">
    Create `.github/workflows/abv-ci.yml` in your repository:

    ```yaml theme={null}
    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
  </Accordion>

  <Accordion title="Step 2: Create GitHub Token for Actions" icon="key">
    Generate a GitHub Personal Access Token with appropriate permissions.

    **Token creation steps:**

    1. Go to **GitHub Settings** → **Developer settings** → **Personal access tokens**
    2. Click **Generate new token**
    3. 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`                            |

    4. Generate token and copy it immediately (won't be shown again)
    5. 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.
  </Accordion>

  <Accordion title="Step 3: Configure ABV Webhook for GitHub Actions" icon="webhook">
    Configure ABV to send webhooks to GitHub's repository\_dispatch API.

    **Configuration steps:**

    1. In ABV dashboard, navigate to **Prompts** → **Webhooks**
    2. Click **Create Webhook**
    3. Set the following fields:

    **Endpoint URL:**

    ```
    https://api.github.com/repos/{owner}/{repo}/dispatches
    ```

    Replace `{owner}` with your GitHub username or organization, and `{repo}` with repository name.

    **Example:**

    ```
    https://api.github.com/repos/acme-corp/production-app/dispatches
    ```

    **Headers:**
    Add two headers:

    ```
    Accept: application/vnd.github+json
    Authorization: Bearer {your_github_token}
    ```

    Replace `{your_github_token}` with the PAT created in Step 2.

    **Request body template** (ABV automatically sends this):

    ```json theme={null}
    {
      "event_type": "abv-prompt-update",
      "client_payload": {
        "action": "{{action}}",
        "prompt": {{prompt}}
      }
    }
    ```

    4. **(Optional)** Filter events by labels or tags to reduce noise
    5. Click **Save**

    **Important:** ABV encrypts and securely stores your GitHub token in the Authorization header.
  </Accordion>

  <Accordion title="Step 4: Test GitHub Actions Integration" icon="vial">
    Verify the integration works end-to-end.

    **Testing steps:**

    1. **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)

    2. **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

    3. **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)

    4. **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).
  </Accordion>
</AccordionGroup>

# Implementation: Webhook Server (Git Sync)

<AccordionGroup>
  <Accordion title="Architecture Overview" icon="diagram-project">
    The webhook server receives prompt change events from ABV and commits them to your GitHub repository.

    **Flow diagram:**

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-github-integration-48c8ed42.png" alt="GitHub Integration Flow" />

    **Workflow:**

    1. User saves prompt in ABV
    2. ABV sends webhook POST to your server
    3. Server validates webhook signature
    4. Server fetches current file SHA from GitHub
    5. Server commits updated prompt JSON to repository
    6. 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
  </Accordion>

  <Accordion title="Step 1: Configure ABV Webhook for Sync" icon="webhook">
    Set up a webhook in ABV to send events to your webhook server.

    **Configuration steps:**

    1. In ABV dashboard, navigate to **Prompts** → **Webhooks**
    2. Click **Create Webhook**
    3. Configure the following:

    **Endpoint URL:**

    ```
    https://your-domain.com/webhook/prompt
    ```

    (You'll deploy the server in later steps)

    **Events:** (optional filters)

    * `created`: Trigger when new prompt versions are created
    * `updated`: Trigger when prompts are updated
    * `deleted`: Trigger when prompts are deleted

    Default: all events selected.

    **Signing Secret:**

    * ABV generates a signing secret automatically
    * Copy this secret and save it securely (you'll need it for webhook verification)

    4. Click **Save**

    **Sample webhook payload:**

    ```json theme={null}
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "timestamp": "2024-07-10T10:30:00Z",
      "type": "prompt-version",
      "action": "created",
      "prompt": {
        "id": "prompt_abc123",
        "name": "movie-critic",
        "version": 3,
        "projectId": "xyz789",
        "labels": ["production", "latest"],
        "prompt": "As a {{criticLevel}} movie critic, rate {{movie}} out of 10.",
        "type": "text",
        "config": {},
        "commitMessage": "Improved critic persona",
        "tags": ["entertainment"],
        "createdAt": "2024-07-10T10:30:00Z",
        "updatedAt": "2024-07-10T10:30:00Z"
      }
    }
    ```

    **Note:** Your webhook endpoint must return 2xx status codes for successful processing. ABV retries failed webhooks with exponential backoff.
  </Accordion>

  <Accordion title="Step 2: Prepare GitHub Repository and Token" icon="github">
    Set up GitHub repository and create a PAT for API access.

    **Create `.env` file** with configuration:

    ```bash theme={null}
    # 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:<br />• **Contents**: Read and write<br />• **Metadata**: Read-only |
    | **Classic PAT**                    | • `public_repo` (for public repositories)<br />• `repo` (for private repositories)         |

    **PAT creation:**

    1. GitHub **Settings** → **Developer settings** → **Personal access tokens**
    2. **Generate new token** (fine-grained recommended)
    3. Select repository access (specific repo or all repos)
    4. Set permissions as listed above
    5. Generate and copy token
    6. Add to `.env` file as `GITHUB_TOKEN`

    **Security:** Fine-grained PATs expire and can be scoped to specific repositories, reducing security risk.
  </Accordion>

  <Accordion title="Step 3: Implement FastAPI Webhook Server" icon="code">
    Create a webhook server that receives ABV events and commits to GitHub.

    **Create `main.py`:**

    ```python theme={null}
    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:**

    ```bash theme={null}
    pip install fastapi uvicorn pydantic-settings httpx
    ```

    **Run locally:**

    ```bash theme={null}
    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:

    ```bash theme={null}
    ngrok http 8000
    # Use ngrok URL in ABV webhook configuration
    ```
  </Accordion>

  <Accordion title="Step 4: Deploy Webhook Server" icon="cloud-arrow-up">
    Deploy the webhook server to a public HTTPS endpoint.

    **Deployment options:**

    **Option 1: Render.com (recommended for beginners)**

    1. Create `requirements.txt`:
       ```
       fastapi
       uvicorn[standard]
       pydantic-settings
       httpx
       ```
    2. Create `render.yaml`:
       ```yaml theme={null}
       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
       ```
    3. Push to GitHub and connect repository in Render dashboard
    4. Set environment variables in Render dashboard
    5. Deploy

    **Option 2: Fly.io**

    1. Install Fly CLI: `curl -L https://fly.io/install.sh | sh`
    2. Run `fly launch` and follow prompts
    3. Set secrets: `fly secrets set GITHUB_TOKEN=... GITHUB_REPO_OWNER=... GITHUB_REPO_NAME=...`
    4. Deploy: `fly deploy`

    **Option 3: Heroku**

    1. Create `Procfile`:
       ```
       web: uvicorn main:app --host 0.0.0.0 --port $PORT
       ```
    2. Deploy via Heroku CLI or GitHub integration
    3. Set config vars in Heroku dashboard

    **After deployment:**

    1. Note your public HTTPS URL (e.g., `https://abv-sync.onrender.com`)
    2. Update ABV webhook endpoint to `https://your-domain.com/webhook/prompt`
    3. Test by updating a prompt in ABV
    4. Verify new commit appears in GitHub repository
  </Accordion>

  <Accordion title="Testing and Troubleshooting" icon="wrench">
    Verify the webhook server is working correctly.

    **Test health endpoint:**

    ```bash theme={null}
    curl https://your-domain.com/status
    # Should return: {"healthy": true}
    ```

    **Test webhook endpoint manually:**

    ```bash theme={null}
    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:**

    ```json theme={null}
    {
      "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`
  </Accordion>
</AccordionGroup>

# Advanced Patterns

<AccordionGroup>
  <Accordion title="Filter by Label (Production Only)" icon="filter">
    Sync only prompts with specific labels (e.g., `production`) to avoid cluttering git history with experiments.

    **In webhook server `.env`:**

    ```bash theme={null}
    REQUIRED_LABEL=production
    ```

    **Behavior:**

    * Prompts **with** `production` label: synced to GitHub
    * Prompts **without** `production` label: skipped (webhook returns success without committing)

    **In GitHub Actions:**

    ```yaml theme={null}
    # 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.
  </Accordion>

  <Accordion title="Multi-File Organization" icon="folder-tree">
    Store different prompts in separate files for better organization.

    **Modify webhook server to use prompt name as file path:**

    ```python theme={null}
    # 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.
  </Accordion>

  <Accordion title="Trigger Multiple Workflows" icon="sitemap">
    Trigger different workflows based on prompt metadata (labels, tags, name patterns).

    **GitHub Actions with conditional workflows:**

    ```yaml theme={null}
    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`
  </Accordion>

  <Accordion title="Signature Verification for Security" icon="lock">
    Verify webhook signatures to ensure requests come from ABV and haven't been tampered with.

    **Add to webhook server:**

    ```python theme={null}
    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
  </Accordion>
</AccordionGroup>

# Next Steps

<CardGroup cols={2}>
  <Card title="Webhook & Slack Integration" icon="slack" href="/developer/prompt-management/webhooks-slack-integration">
    Send prompt change notifications to Slack channels using webhooks
  </Card>

  <Card title="Get Started with Prompt Management" icon="rocket" href="/developer/prompt-management/get-started">
    Complete quickstart guide for creating and deploying prompts
  </Card>

  <Card title="Version Control" icon="code-branch" href="/developer/prompt-management/version-control">
    Deploy and rollback prompts safely using labels and versions
  </Card>

  <Card title="A/B Testing Prompts" icon="flask" href="/developer/prompt-management/ab-testing-llm-prompts">
    Run statistical A/B tests on prompt variants in production
  </Card>
</CardGroup>
