Menu

Scheduled Workflows

Automate Snipara operations using external schedulers like GitHub Actions or system cron. Keep the API key in the scheduler's secret store, never in a committed workflow or a database cron definition.

Philosophy

Snipara optimizes context. Scheduling is a solved problem — use the right tool for each job.

Quick Start

Schedules, polling intervals, job durations, and “All Plans” labels on this page are operator examples unless the active product contract says otherwise. Hosted job availability and cadence can vary by plan, provider, queue, and deployment; verify them before treating a value as an SLO.

Trigger a reindex with a single curl command:

curl -X POST "https://api.snipara.com/v1/{project}/reindex" \
  -H "X-API-Key: snp-your-api-key"

Available Scheduled Operations

OperationEndpointUse Case
ReindexPOST /v1/{project}/reindexRefresh embeddings after content changes
Memory reviewMemory review queueEmit review decisions for stale, duplicate, or low-signal candidates
PR Answer Pack generationHosted schedulerProcess queued pull request Answer Packs
PR Answer Pack publicationHosted schedulerPublish ready packs to GitHub Check Runs
Index healthMCP snipara_index_healthMonitor documentation quality

Option 1: GitHub Actions

The easiest option for GitHub-hosted projects. Create a workflow file to trigger Snipara operations on a schedule or after pushes.

Daily Reindex

Create .github/workflows/snipara-reindex.yml:

name: Snipara Daily Reindex
on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM UTC
  workflow_dispatch:  # Allow manual trigger
jobs:
  reindex:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Trigger Snipara Reindex
        env:
          SNIPARA_API_KEY: ${{ secrets.SNIPARA_API_KEY }}
          SNIPARA_PROJECT_ID: ${{ secrets.SNIPARA_PROJECT_ID }}
        run: |
          response=$(curl -s -X POST \
            "https://api.snipara.com/v1/$SNIPARA_PROJECT_ID/reindex" \
            -H "X-API-Key: $SNIPARA_API_KEY")
          
          job_id=$(echo "$response" | jq -r '.job_id')
          echo "Started reindex job: $job_id"

PR/MR Answer Pack Jobs

Pull request and merge request webhooks queue Answer Packs quickly. On the hosted platform, Snipara manages the private server-side scheduler that generates queued packs and publishes ready packs to GitHub or GitLab without blocking webhook delivery.

Self-hosted operators should keep job routes, internal credentials, and scheduler auth details in private runbooks rather than public integration docs.

Post-Push Sync

Trigger reindex when documentation changes:

name: Snipara Sync on Push
on:
  push:
    paths:
      - 'docs/**'
      - 'README.md'
      - 'CLAUDE.md'
    branches: [main]
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Incremental Reindex
        run: |
          curl -X POST \
            "https://api.snipara.com/v1/${{ secrets.SNIPARA_PROJECT_ID }}/reindex" \
            -H "X-API-Key: ${{ secrets.SNIPARA_API_KEY }}"
GitHub Secrets: Add SNIPARA_API_KEY and SNIPARA_PROJECT_ID to your repository secrets (Settings → Secrets and variables → Actions).

Option 2: Any Cron Runner

If you already have a cron-capable platform or VPS, trigger the same workflows with a shell script and a standard cron schedule.

Setup

Add a crontab entry like:

# Daily at 02:00 UTC
0 2 * * * /opt/snipara/scripts/snipara-reindex.sh >> /var/log/snipara-reindex.log 2>&1

Use a shell script for retries, polling, and structured logging:

#!/bin/bash
# scripts/snipara-reindex.sh
set -euo pipefail
response=$(curl -s -X POST \
  "https://api.snipara.com/v1/$SNIPARA_PROJECT_ID/reindex?mode=incremental" \
  -H "X-API-Key: $SNIPARA_API_KEY")
job_id=$(echo "$response" | jq -r '.job_id')
echo "[$(date -Iseconds)] Started reindex job: $job_id"
# Poll for completion (max 10 min)
for i in $(seq 1 60); do
  sleep 10
  status=$(curl -s \
    "https://api.snipara.com/v1/$SNIPARA_PROJECT_ID/reindex/$job_id" \
    -H "X-API-Key: $SNIPARA_API_KEY" | jq -r '.status')
  
  [ "$status" = "completed" ] && echo "Done!" && exit 0
  [ "$status" = "failed" ] && echo "Failed!" && exit 1
done

Option 3: pg_cron as a secret-free signal

Do not embed a Snipara API key in cron.job: PostgreSQL stores the scheduled SQL command durably. If database-level scheduling is required, let pg_cron emit only a secret-free notification. A trusted worker outside PostgreSQL can listen for that signal and call Snipara with an API key loaded from its environment or secret manager.

-- Secret-free daily signal at 2 AM UTC
SELECT cron.schedule(
  'snipara-reindex-signal',
  '0 2 * * *',
  $$SELECT pg_notify(
    'snipara_reindex',
    json_build_object('project_id', 'YOUR_PROJECT_ID', 'mode', 'incremental')::text
  )$$
);

Prefer GitHub Actions or another external scheduler unless you already operate the trusted listener. PostgreSQL notifications are transient; the listener is responsible for retries, authentication, and durable job tracking.

Common Scheduled Tasks

Daily Incremental Reindex

Keep embeddings fresh for new/changed documents. Only indexes documents without existing chunks.

POST /v1/{project}/reindex?mode=incremental
Schedule: Daily 2 AM

Weekly Full Reindex

Regenerate all embeddings to catch content drift. Deletes existing chunks first.

POST /v1/{project}/reindex?mode=full
Schedule: Sunday 3 AM

Monthly Memory Review

Review stale, duplicate, and low-signal memory candidates before invalidating or superseding them. Automated cleanup should emit decisions, not delete durable memory.

snipara-companion memory reviews --emit-decisions
Platform Memory

PR/MR Answer Packs

Generate queued PR/MR Answer Packs, then publish ready packs through the project's configured provider surface.

Managed automatically by the hosted platform; self-hosted job routes belong in private runbooks.

Example cadence: every 5 min

Daily Index Health Check

Monitor documentation coverage and quality. Integrate with alerting.

snipara_index_health()
Availability: verify active plan

Best Practices

Idempotency

The reindex endpoint handles idempotency automatically:

{
  "job_id": "existing-job-id",
  "already_exists": true,
  "status": "running"
}

If a job is already running, a new one won't be created.

Error Handling

Always check response status:

response=$(curl -s -w "\n%{http_code}" -X POST "$API_URL/v1/$PROJECT/reindex" \
    -H "X-API-Key: $API_KEY")
http_code=$(echo "$response" | tail -1)
if [ "$http_code" != "200" ] && [ "$http_code" != "201" ]; then
  echo "ERROR: HTTP $http_code"
  # Send alert (Slack, PagerDuty, etc.)
  exit 1
fi

Timeouts

The durations below are planning estimates for operator timeouts, not platform performance guarantees.

OperationTypical DurationRecommended Timeout
Incremental reindex (small)10-30s5 min
Incremental reindex (large)1-5 min15 min
Full reindex5-30 min45 min

Security

Never commit API keys to version control. Use secrets/environment variables provided by your CI/CD platform.
PlatformSecret Storage
GitHub ActionsRepository Secrets
Hosted cron runnersEnvironment Variables
pg_cron signal + trusted workerWorker environment or external secret manager; never cron.job
Local cronEnvironment file (chmod 600)

Monitoring

Check the Snipara dashboard for:

  • Recent index jobs with status
  • Index health metrics
  • Memory usage over time

Open https://www.snipara.com/dashboard/projects/{project}, then select the Context tab.

Next Steps