All posts
Guide

Self-Hosting SearchFit Content Generation in CI

Self-host SearchFit content generation in GitHub Actions or CircleCI. Get AI-optimized content auto-triggered, version-controlled, and validated - no manual

KKevin10 minutes read

ChatGPT, Perplexity, Gemini, and Claude are answering your prospects' questions right now. If your content isn't getting cited, your traffic is leaking to competitors who've figured out answer engine optimisation. SearchFit content generation already creates articles engineered to rank inside those AI answer engines: it's built on a multi-agent architecture that researches, writes, validates, and scores every piece. But clicking "Generate" in a dashboard doesn't scale when you need 50 articles a week and every piece must pass a series of quality gates.

Self-hosting that generation inside your CI pipeline changes everything. You write a topic file, push to a repo, and the pipeline fires off content creation through SearchFit's API. The result lands in a staging branch or your CMS, every article checked by a validator and scorer agent before anyone on your team sees it. No one waits. No one babysits a dashboard. No one questions whether the content is built for AI visibility.

This guide walks through the exact setup, from containerizing the worker to wiring up GitHub Actions or CircleCI. You'll leave with a repeatable AEO content factory that lives alongside your code.

Prerequisites

You need:

  • A SearchFit account with API access. If you haven't already, grab your credentials from the OAuth and API Key Management page and scope a token for the content generation endpoint.
  • Docker installed locally for building and testing your worker image.
  • A CI platform - GitHub Actions, CircleCI, GitLab CI, or any runner that can execute containers.
  • Basic familiarity with shell scripting, YAML, and environment variable management.
  • A clear list of the first 10-20 topics you want to generate. Store them in a simple YAML or JSON file so the pipeline can iterate.

You'll also want a working knowledge of SearchFit's API. The Building Custom AEO Workflows With the SearchFit API guide walks through authentication, request bodies, and response parsing. Bookmark it.

Step 1: Understand SearchFit's Multi-Agent Content Generation

Before you automate, you need to know what you're triggering. SearchFit doesn't just prompt an LLM and hope. Each piece of content goes through a team of specialized agents:

  1. Researcher - pulls in the latest citations, competitor snippets, and topical authority signals from across ChatGPT, Perplexity, Gemini, and Claude.
  2. Writer - generates the article, structured to match what those engines cite.
  3. Validator - checks for hallucinations, factual grounding, and structural compliance with AEO best practices.
  4. Scorer - predicts how likely the content is to be cited in each target engine and provides a plain-English pass/fail.

That pipeline is exposed through a single API endpoint. You send a topic, a target persona, and a handful of configuration flags. You get back a fully formed article - or a rejection if the scorer doesn't give the green light. When you self-host inside CI, you're calling that endpoint repeatedly and handling the outcomes programmatically.

Pro Tip: Always run content through the validation gate before publishing. The autonomous content validation service catches things even good editors miss - invented stats, contradictory claims, and off-voice phrasing that would get rejected by an AI answer engine.

Step 2: Containerize the Content Generation Worker

CI pipelines run arbitrary code, but the safest, most repeatable pattern is to ship a Docker image. You'll write a small script that calls SearchFit's API, wrap it in a Dockerfile, and push it to your registry. This image becomes the workhorse every CI job uses.

Start with a minimal base image. Alpine Linux with Python works well if you're using the Python SDK; a Node slim image if you prefer TypeScript. The key is to include only what's necessary. Docker's official documentation covers multi-stage builds and layer caching, but here's the practical checklist:

  • Install curl, jq, and any HTTP client your script needs.
  • Copy your generation script into the image.
  • Set an entrypoint that reads environment variables for SEARCHFIT_API_KEY, SEARCHFIT_TOPIC_FILE, and optional flags like DRY_RUN.
  • Never bake credentials into the image. Inject them at runtime through CI secrets.
FROM alpine:3.19
RUN apk add --no-cache curl jq bash
WORKDIR /app
COPY generate.sh .
RUN chmod +x generate.sh
ENTRYPOINT ["/app/generate.sh"]

The generate.sh script can be as simple as looping over topics and POSTing to the API. A production version includes retry logic, exponential backoff, and structured logging.

Warning: If your organization uses self-hosted runners on Kubernetes or bare metal, pin your image digest in the CI config. Floating tags lead to broken pipelines when upstream base images shift. Kubernetes documentation explains how to enforce image pull policies if you're scheduling these jobs on a cluster.

Step 3: Write the CI Pipeline Script

The script that lives inside the container is the heart of the operation. It reads a list of topics, calls the SearchFit API for each, and writes the generated markdown files to a shared volume or artifact store.

A minimal Bash implementation looks like this:

#!/bin/bash
set -euo pipefail

API_KEY="${SEARCHFIT_API_KEY:?Missing API key}"
TOPIC_FILE="${SEARCHFIT_TOPIC_FILE:-/app/topics.json}"
OUTPUT_DIR="${OUTPUT_DIR:-/output}"
mkdir -p "$OUTPUT_DIR"

while IFS= read -r topic; do
  echo "Generating: $topic"
  response=$(curl -s -X POST "https://api.searchfit.ai/v1/generate" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"topic\":\"$topic\",\"engine_targets\":[\"chatgpt\",\"perplexity\",\"gemini\",\"claude\"]}")

  # Check if scorer passed and article returned
  if echo "$response" | jq -e '.status == "generated"' > /dev/null; then
    slug=$(echo "$topic" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')
    echo "$response" | jq -r '.content' > "${OUTPUT_DIR}/${slug}.md"
    echo "Success: ${OUTPUT_DIR}/${slug}.md"
  else
    echo "Skipped: $topic (scorer rejected or API error)"
  fi
  sleep 2
done < "$TOPIC_FILE"

This script handles the core loop. In a real pipeline, you'd extend it with:

  • Artifact upload: push generated files to a CI artifact store or S3-compatible bucket.
  • Webhook callback: notify Slack or a project management tool when a batch completes.
  • Citation check post-generation: before closing the job, query the real-time citation monitoring endpoint to confirm the base topic is already showing up in target engines (optional but powerful for existing content refreshes).

If batch generation is your use case, follow the pattern in Parallel Agents: How We Generate 30 Articles in the Time of One. You'll split the topic list into chunks and fan out across CI matrix jobs.

Step 4: Configure Your CI Platform

Now that the container and script are ready, wire them into your CI system. Both GitHub Actions and CircleCI are covered here. Choose the one your team already uses.

GitHub Actions

Create .github/workflows/searchfit-generate.yml:

name: SearchFit Content Generator
on:
  push:
    paths:
      - 'topics/*.json'
  schedule:
    - cron: '0 6 * * 1'  # Monday mornings
jobs:
  generate:
    runs-on: ubuntu-latest
    container:
      image: your-registry.com/searchfit-generator:latest
      credentials:
        username: ${{ secrets.DOCKER_USER }}
        password: ${{ secrets.DOCKER_PASS }}
    steps:
      - name: Checkout topics
        uses: actions/checkout@v4
      - name: Run generation
        run: generate.sh
        env:
          SEARCHFIT_API_KEY: ${{ secrets.SEARCHFIT_API_KEY }}
          SEARCHFIT_TOPIC_FILE: topics/current.json
          OUTPUT_DIR: generated
      - name: Upload articles
        uses: actions/upload-artifact@v4
        with:
          name: generated-content
          path: generated/

This workflow runs whenever a topic file changes, or on a weekly schedule. It checks out the repo, runs the container, and uploads the generated markdown as a build artifact. The official GitHub Actions documentation covers more advanced triggers and environment handling.

Pro Tip: Use the schedule event for evergreen content refreshes. Set a cron that generates new variants of high-traffic pages every month so they stay fresh inside AI answer engines. Combine with the scorer output to only push articles that exceed a threshold.

CircleCI

For CircleCI, define .circleci/config.yml:

version: 2.1
jobs:
  generate-content:
    docker:
      - image: your-registry.com/searchfit-generator:latest
        auth:
          username: $DOCKER_USER
          password: $DOCKER_PASS
    steps:
      - checkout
      - run:
          name: Generate content
          command: generate.sh
          environment:
            SEARCHFIT_API_KEY: $SEARCHFIT_API_KEY
            SEARCHFIT_TOPIC_FILE: topics/current.json
            OUTPUT_DIR: generated
      - store_artifacts:
          path: generated
          destination: content
workflows:
  weekly-content:
    triggers:
      - schedule:
          cron: "0 6 * * 1"
          filters:
            branches:
              only: main
    jobs:
      - generate-content

CircleCI's official docs walk through artifact storage and scheduling. Use store_artifacts to keep generated content in the build output for review or downstream jobs.

Self-Hosted Runners and Infrastructure

If you're running your own runners - perhaps on Kubernetes or EC2 - the same container works, but you need to ensure the environment has access to your private registry and required secrets. Terraform documentation and Ansible documentation both cover provisioning and configuring repeatable CI environments. Use them to define the runner infrastructure as code, then point your CI config at those runners.

Warning: Never hardcode credentials in infrastructure-as-code repos. Use a secrets manager - HashiCorp Vault, AWS Secrets Manager, or the CI platform's native secrets - and inject at runtime. The OAuth and API Key Management in SearchFit guide explains token scoping and rotation, which you should adopt alongside your CI secrets strategy.

Step 5: Scheduling and Triggering Generation

Hardcoded cron jobs are the starting point, but real content ops teams need more flexibility. Integrate topic requests from your editorial calendar, your CMS, or even a Slack command.

  • Slack → CI: Set up a slash command that appends a topic to a topics/queue.json file and pushes to a dedicated branch. The CI pipeline picks it up and runs immediately.
  • CMS webhook: When a content request is created in your project management tool, trigger the CI pipeline via a platform webhook. Most CI services provide an API for triggering builds.
  • n8n workflows: If your team already uses n8n for automation, the Integrating SearchFit With n8n for Self-Hosted Teams guide shows how to create a low-code trigger that sends topics to the SearchFit API and stores results back in your stack. You can also call the CI trigger from an n8n node, bridging the two worlds.

The key is that non-technical stakeholders never need to touch YAML. They submit a topic; the pipeline does the rest.

Step 6: Scale with Parallel Agent Execution

Generating one article at a time is a bottleneck when you need 50+ pieces. SearchFit's own agent team uses a fan-out architecture documented in Parallel Agents: How We Generate 30 Articles in the Time of One. You can replicate that in your CI config.

In GitHub Actions, use a matrix strategy:

jobs:
  generate:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        topic_file: ['topics/batch1.json', 'topics/batch2.json', 'topics/batch3.json']
    container:
      image: your-registry.com/searchfit-generator:latest
    steps:
      - uses: actions/checkout@v4
      - run: generate.sh
        env:
          SEARCHFIT_API_KEY: ${{ secrets.SEARCHFIT_API_KEY }}
          SEARCHFIT_TOPIC_FILE: ${{ matrix.topic_file }}

Each topic file runs in a parallel job, so 3 batches complete in the time of 1. Push it further by splitting topic lists inside the script and spawning background processes - but watch API rate limits. Add a --parallel N flag to your script that throttles concurrency.

Pro Tip: Combine parallel generation with the Building AEO Agents on Top of SearchFit MCP pattern to have each parallel worker run its own agent check after generation. That way, validation scales linearly with generation, keeping total job time flat.

Step 7: Post-Generation Validation and Deployment

The output of your CI job is a folder of markdown files. Don't publish them blindly. Build a validation gate that runs a scorer agent on each article and only passes ones that exceed a threshold.

SearchFit's content generation endpoint already includes a pass/fail from the scorer, as shown in Step 3. But you can add a second pass - a separate CI job that takes the generated artifact, calls the validation endpoint for each file, and produces a filtered set. The autonomous content validation architecture runs entirely via API, so you can script it into a post-generation step.

After validation, deployment can be:

  • A push to your static site repo (Hugo, Next.js, etc.) via a Pull Request.
  • Direct ingestion into your CMS using its API.
  • An update to your real-time citation monitoring config so you immediately track the new content's visibility in ChatGPT, Perplexity, Gemini, and Claude.

For teams that want to incorporate the generated content into their broader AEO strategy, the 10 Questions You Can Ask the SearchFit MCP Server guide offers prompts to analyze new content for AI visibility gaps - useful as a final manual review step before publishing.

Pro Tips and Common Pitfalls

  • Secrets rotation: API keys expire or get rotated. Use the OAuth and API Key Management guide to set up short-lived tokens and automate rotation in your CI secret store.
  • Caching Docker layers: If you're rebuilding the worker image frequently, use layer caching in CI to speed up builds. Both GitHub Actions and CircleCI support Docker layer caching natively.
  • Dry-run mode: Add a DRY_RUN=true flag to your script that writes expected topics and skips API calls. This lets you test pipeline logic without consuming API credits.
  • Rate limits: SearchFit's API enforces rate limits. For batch generation, read the headers (X-RateLimit-Remaining) and sleep accordingly. Log every skipped or failed generation so you can retry selectively.
  • Don't generate in isolation: After content goes live, use Real-Time Citation Monitoring to watch when it gets picked up by AI engines. That feedback loop tells you which topics and structures win, so you can adjust your topic files.

Warning: Avoid putting raw content files directly into your main branch. Always generate into a staging directory, run validation, and then open a PR. This keeps your main branch clean and gives editors a chance to review scored output.

Conclusion: Take Control of AI Visibility

Self-hosting SearchFit content generation inside CI turns a manual, dashboard-bound process into an automated AEO factory that scales with your team. Instead of waiting for someone to click "Generate," you push a list of topics and the pipeline produces validated, AI-optimized content that's ready for review or direct deployment.

Key takeaways:

  • Containerization makes the pipeline portable and repeatable; every run uses an identical environment.
  • CI-native secret management keeps API credentials secure and rotation simple.
  • Parallel execution - whether via CI matrix builds or fan-out scripts - cuts batch generation time by 90% or more.
  • Post-generation validation gates ensure only content that passes the scorer threshold reaches your editors.
  • Linking the pipeline to real-time citation monitoring closes the loop, proving that your content actually ranks in ChatGPT, Perplexity, Gemini, and Claude.

Start with the sample GitHub Actions workflow above, adjust for your team's stack, and push the first topic file. In the time it takes to review a Pull Request, you'll have a dozen articles that are built to get cited where your audience now searches.

Get SearchFIT Weekly

What we are learning about getting brands cited in AI search, in your inbox every week. Unsubscribe any time.