Implement support for output schemas (#411)

* tweak examples

* tweak prompt

* Implement support for output schemas

* fix: add example for structured output with zod schema

* tweak

* remove redundant cast

* fix input name

* strip $schema

* hack around vendor requirement

* clarify required result output

---------

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
This commit is contained in:
Mateusz Burzyński
2026-03-05 23:07:03 +00:00
committed by pullfrog[bot]
parent fafe930c77
commit 5684cbef77
11 changed files with 5981 additions and 89 deletions
+110 -10
View File
@@ -1,5 +1,5 @@
<!-- test preview system --> <!-- test bypass 2 --> <!-- trigger preview repo creation -->
<p align="center">
<!-- test preview system -->
<p align="center">
<h1 align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://pullfrog.com/frog-white-200px.png">
@@ -24,27 +24,26 @@ Pullfrog is a GitHub bot that brings the full power of your favorite coding agen
- **Tag `@pullfrog`** — Tag `@pullfrog` in a comment anywhere in your repo. It will pull in any relevant context using the action's internal MCP server and perform the appropriate task.
- **Prompt from the web** — Trigger arbitrary tasks from the Pullfrog dashboard
- **Automated triggers** — Configure Pullfrog to trigger agent runs in response to specific events. Each of these triggers can be associated with custom prompt instructions.
- **Automated triggers** — Configure Pullfrog to trigger agent runs in response to specific events. Each of these triggers can be associated with custom prompt instructions.
- issue created
- issue labeled
- PR created
- PR review created
- PR review created
- PR review requested
- and more...
Pullfrog is the bridge between your preferred coding agents and GitHub. Use it for:
- **🤖 Coding tasks** — Tell `@pullfrog` to implement something and it'll spin up a PR. If CI fails, it'll read the logs and attempt a fix automatically. It'll automatically address any PR reviews too.
- **🔍 PR review** — Coding agents are great at reviewing PRs. Using the "PR created" trigger, you can configure Pullfrog to auto-review new PRs.
- **🤙 Issue management** — Via the "issue created" trigger, Pullfrog can automatically respond to common questions, create implementation plans, and link to related issues/PRs. Or (if you're feeling lucky) you can prompt it to immediately attempt a PR addressing new issues.
- **Literally whatever** — Want to have the agent automatically add docs to all new PRs? Cut a new release with agent-written notes on every commit to `main`? Pullfrog lets you do it.
<!-- Features
- **Agent-agnostic** — Switch between agents with the click of a radio button.
- ** -->
<!--
<!--
## Get started
Install the Pullfrog GitHub App on your personal or organization account. During installation you can choose to limit access to a specific repo or repos. After installation, you'll be redirected to the Pullfrog dashboard where you'll see an onboarding flow. This flow will create your `pullfrog.yml` workflow and prompt you to set up API keys. Once you finish those steps (2 minutes) you're ready to rock.
@@ -124,14 +123,14 @@ on:
pull_request_review:
types: [submitted]
# add other triggers as needed
jobs:
pullfrog:
# trigger conditions (e.g. only run if @pullfrog is mentioned)
if: contains(github.event.comment.body, '@pullfrog') || contains(github.event.issue.body, '@pullfrog')
permissions:
id-token: write
contents: write
@@ -148,3 +147,104 @@ jobs:
</details>
-->
## Standalone Usage
You can also use `pullfrog/pullfrog` as a step in your own workflows. The action exposes a `result` output that can be consumed by subsequent steps.
### Example: Auto-generate release notes on new tags
```yaml
name: Release
on:
push:
tags: ['v*']
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate release notes
id: notes
uses: pullfrog/pullfrog@v0
with:
prompt: |
Generate release notes for ${{ github.ref_name }}.
Compare commits between this tag and the previous tag.
Format as markdown: summary paragraph, then ### Features, ### Fixes, ### Breaking Changes sections.
Omit empty sections. Be concise.
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# write to file to avoid shell escaping issues with special characters
- name: Create GitHub release
run: |
notesfile="$RUNNER_TEMP/release-notes-$GITHUB_RUN_ID.md"
printf '%s' "$NOTES" > "$notesfile"
gh release create ${{ github.ref_name }} --title "${{ github.ref_name }}" --notes-file "$notesfile"
env:
GH_TOKEN: ${{ github.token }}
NOTES: ${{ steps.notes.outputs.result }}
```
### Example: Structured Output with Zod Schema
You can force the agent to return structured JSON output by providing a JSON schema. This allows you to reliably parse and use the agent's response in subsequent workflow steps.
You can define your JSON schema directly or uou can use any validation library that converts to JSON Schema. Here's an example using [Zod](https://zod.dev):
```yaml
name: Release Check
on:
pull_request:
types: [closed]
jobs:
check-release:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm install --no-save --no-package-lock zod @actions/core
- name: Generate Schema
id: schema
run: |
node -e '
import { z } from "zod";
import { setOutput } from "@actions/core";
const schema = z.object({
version: z.string().describe("Semantic version number (e.g. 1.0.0)"),
isBreaking: z.boolean().describe("Whether this release contains breaking changes"),
changelog: z.array(z.string()).describe("List of changes in this release"),
});
setOutput("schema", JSON.stringify(z.toJSONSchema(schema)));
'
- name: Analyze PR
id: analysis
uses: pullfrog/pullfrog@v0
with:
prompt: |
Analyze this PR and determine semantic versioning impact.
Return a JSON object matching the provided schema.
output_schema: ${{ steps.schema.outputs.schema }}
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Process Result
run: |
# Parse the JSON result using fromJSON()
echo "Version: ${{ fromJSON(steps.analysis.outputs.result).version }}"
echo "Breaking: ${{ fromJSON(steps.analysis.outputs.result).isBreaking }}"
```