Custom Poller Example
This guide shows how to create a custom poller in your own repository that invokes fullsend harness agents directly, bypassing the standard GitHub event trigger flow.
Use Case
Custom pollers are useful when you want to:
- Poll external systems (Jira, Linear, Slack, etc.) on a schedule
- Trigger harness agents based on custom logic
- Reuse fullsend's harness infrastructure without duplicating workflow code
Example: Jira Polling Workflow
This example polls Jira for bugs and dispatches fullsend agents to process them:
name: Fullsend Jira Poll
on:
schedule:
- cron: '*/30 * * * *' # every 30 minutes
workflow_dispatch:
permissions:
actions: write
contents: write
id-token: write
issues: write
packages: read
pull-requests: write
jobs:
poll:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.dispatch.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install fullsend CLI
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download --repo fullsend-ai/fullsend \
-p 'fullsend_*_linux_amd64.tar.gz' -O - | tar xz
sudo mv fullsend /usr/local/bin/
- name: Poll Jira and build dispatch matrix
id: dispatch
env:
JIRA_TOKEN: ${{ secrets.JIRA_TOKEN }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_BASE_URL: ${{ vars.JIRA_BASE_URL }}
TARGET_REPO: ${{ github.repository }}
run: |
fullsend poll \
--input-driver jira-poll \
--jira-url "${JIRA_BASE_URL}" \
--jira-project MYPROJECT \
--jql 'project=MYPROJECT and statusCategory != Done and updated > -1week and type=Bug' \
--target-repo "${TARGET_REPO}" \
--output dispatches.json \
--fullsend-dir .fullsend
# Build GitHub Actions matrix format
if ! jq -e 'length > 0' dispatches.json > /dev/null 2>&1; then
echo 'matrix={"include":[]}' >> "${GITHUB_OUTPUT}"
exit 0
fi
MATRIX=$(jq -c '{include: .}' dispatches.json)
DELIM="MATRIX_$(openssl rand -hex 8)"
{
echo "matrix<<${DELIM}"
printf '%s' "${MATRIX}"
echo
echo "${DELIM}"
} >> "${GITHUB_OUTPUT}"
harness:
needs: poll
uses: fullsend-ai/fullsend/.github/workflows/reusable-dispatch.yml@main
with:
matrix: ${{ needs.poll.outputs.matrix }}
mint_url: ${{ vars.FULLSEND_MINT_URL }}
gcp_region: ${{ vars.FULLSEND_GCP_REGION }}
jira_base_url: ${{ vars.JIRA_BASE_URL }}
secrets:
FULLSEND_GCP_WIF_PROVIDER: ${{ secrets.FULLSEND_GCP_WIF_PROVIDER }}
FULLSEND_GCP_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
OTEL_EXPORTER_OTLP_TRACES_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_TRACES_HEADERS }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
JIRA_TOKEN: ${{ secrets.JIRA_TOKEN }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}Matrix Format
The matrix input (a GitHub Actions matrix strategy that runs parallel jobs) must follow the format produced by fullsend dispatch --output-driver gha-matrix:
{
"include": [
{
"agent": "agent-name",
"source_repo": "org/repo",
"role": "harness",
"event_payload": "{...}",
"status_repo": "org/repo",
"status_number": "123"
}
]
}Prerequisites
Your external repository needs these variables and secrets configured:
Variables:
FULLSEND_MINT_URL- Token mint service URLFULLSEND_GCP_REGION- GCP region for Vertex AIOTEL_EXPORTER_OTLP_ENDPOINT- OpenTelemetry endpoint (optional)JIRA_BASE_URL- Jira instance URL (if using Jira agents)
Secrets:
FULLSEND_GCP_WIF_PROVIDER- GCP Workload Identity Federation (WIF) providerFULLSEND_GCP_PROJECT_ID- GCP project IDOTEL_EXPORTER_OTLP_TRACES_HEADERS- OTEL auth headers (optional)JIRA_TOKEN- Jira API token (if using Jira agents)JIRA_USER_EMAIL- Jira user email (if using Jira agents)
How It Works
- Poll job runs your custom logic to query an external system and builds a dispatch matrix
- Harness job calls
reusable-dispatch.ymlwith the pre-computed matrix reusable-dispatch.ymlskips the routing and dispatch steps (see architecture.md for the standard dispatch flow), directly invokingharness-runwith your matrix- Harness agents execute according to your matrix configuration
Permissions
The top-level permissions: block grants the maximum permissions required by reusable-dispatch.yml. Even though you're only running harness agents via the pre-computed matrix, GitHub validates that the caller grants sufficient permissions for all jobs in the reusable workflow (including code and fix jobs that won't actually run).
Required permissions:
contents: write- needed by code/fix agentspackages: read- needed by code/fix agentsactions: write,id-token: write,issues: write,pull-requests: write- needed by all agents
Authorization
When using a pre-computed matrix, the .fullsend/config.yaml agent-enablement checks are bypassed. The token mint service acts as the authorization boundary (see mint-administration.md) - ensure your mint service is properly configured to control which agents external callers can invoke.
