{"id":35429913,"url":"https://github.com/fro-bot/agent","last_synced_at":"2026-06-13T03:08:40.868Z","repository":{"id":331955000,"uuid":"1126485011","full_name":"fro-bot/agent","owner":"fro-bot","description":"@fro-bot Agent","archived":false,"fork":false,"pushed_at":"2026-05-23T19:17:09.000Z","size":13566,"stargazers_count":1,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T19:17:22.829Z","etag":null,"topics":["actions","agent","automation","bot","fro-bot","github-actions","github-app"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fro-bot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-02T02:23:08.000Z","updated_at":"2026-05-23T19:09:29.000Z","dependencies_parsed_at":"2026-04-02T11:05:15.395Z","dependency_job_id":null,"html_url":"https://github.com/fro-bot/agent","commit_stats":null,"previous_names":["fro-bot/agent"],"tags_count":191,"template":false,"template_full_name":"bfra-me/github-action","purl":"pkg:github/fro-bot/agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fro-bot%2Fagent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fro-bot%2Fagent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fro-bot%2Fagent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fro-bot%2Fagent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fro-bot","download_url":"https://codeload.github.com/fro-bot/agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fro-bot%2Fagent/sbom","scorecard":{"id":1241157,"data":{"date":"2026-01-11T19:40:30Z","repo":{"name":"github.com/fro-bot/agent","commit":"c4c9b86cb7c9a7efb1dd6fae69e2ad553bfbb37e"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":6,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: RenovateBot: .github/renovate.json5:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"project was created within the last 90 days. Please review its contents carefully","details":["Warn: Repository was created within the last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/ci.yaml:28","Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yaml:17","Warn: no topLevel permission defined: .github/workflows/renovate.yaml:1","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yaml:19","Warn: no topLevel permission defined: .github/workflows/update-repo-settings.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:  23 out of  23 GitHub-owned GitHubAction dependencies pinned","Info:   9 out of   9 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (30) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":1,"reason":"branch protection is not maximal on development and all release branches","details":["Warn: branch protection not enabled for branch 'v0'","Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: codeowners review is not required on branch 'main'","Warn: 'last push approval' is disabled on branch 'main'","Warn: 'up-to-date branches' is disabled on branch 'main'","Info: status check found to merge onto on branch 'main'","Warn: PRs are not required to make changes on branch 'main'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/fro-bot/.github/SECURITY.md:1","Info: Found linked content: github.com/fro-bot/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/fro-bot/.github/SECURITY.md:1","Info: Found text in security policy: github.com/fro-bot/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Contributors","score":10,"reason":"project has 5 contributing companies or organizations","details":["Info: found contributions from: UnrealPhx, bfra-me, ethereumclassic, ps2dev, pspdev"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}},{"name":"CI-Tests","score":10,"reason":"30 out of 30 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}}]},"last_synced_at":"2026-01-12T00:56:03.292Z","repository_id":331955000,"created_at":"2026-01-12T00:56:03.292Z","updated_at":"2026-01-12T00:56:03.292Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33680527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","agent","automation","bot","fro-bot","github-actions","github-app"],"created_at":"2026-01-02T20:17:58.251Z","updated_at":"2026-06-13T03:08:40.855Z","avatar_url":"https://github.com/fro-bot.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"./assets/banner.svg\" alt=\"Fro Bot Agent Banner\" width=\"100%\" /\u003e\n\n# Fro Bot Agent\n\n\u003e AI-powered GitHub automation with persistent memory\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/fro-bot/agent/ci.yaml?style=for-the-badge\u0026label=Build\u0026labelColor=0D0216\u0026color=00BCD4)](https://github.com/fro-bot/agent/actions) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/fro-bot/agent/badge?style=for-the-badge\u0026labelColor=0D0216\u0026color=E91E63)](https://securityscorecards.dev/viewer/?uri=github.com/fro-bot/agent) [![License](https://img.shields.io/badge/License-MIT-FFC107?style=for-the-badge\u0026labelColor=0D0216\u0026color=FFC107)](LICENSE)\n\n[Overview](#overview) · [Quick Start](#quick-start) · [Usage](#usage) · [Configuration](#configuration) · [Development](#development)\n\n\u003c/div\u003e\n\n---\n\n## Overview\n\nFro Bot Agent is a GitHub Action that brings AI automation to your repository using [OpenCode](https://opencode.ai/). It optionally supports [Oh My OpenAgent (oMo)](https://github.com/code-yeongyu/oh-my-openagent) for extended provider and agent workflows when `enable-omo: true` is set. It can respond to issues, review pull requests, participate in discussions, and execute scheduled tasks—all while **remembering previous interactions**.\n\n### Why Fro Bot?\n\nTraditional CI-based AI agents are stateless: they process each request independently, with no memory of past work. This leads to repeated investigations, redundant API calls, and wasted compute time.\n\n**Fro Bot solves this with persistent sessions.** The agent's memory is preserved across workflow runs using GitHub Actions cache (with optional S3 backup), enabling it to:\n\n- **Build institutional knowledge** of your codebase over time\n- **Reference prior investigations** to avoid duplicate work\n- **Learn from past decisions** and maintain consistency\n- **Resume interrupted work** without starting over\n\n### Key Features\n\n- **🔄 Persistent Memory** — Session state survives workflow runs via cache\n- **🤖 Multiple Triggers** — Responds to comments, PRs, issues, reviews, and scheduled events\n- **⚡ Auto-Setup** — Zero-config installation of OpenCode on first run (oMo is opt-in)\n- **👀 User Feedback** — Visual acknowledgment with reactions and labels\n- **🔐 Security-First** — Enforces permission gating and credential hygiene\n- **📊 Observability** — Detailed run summaries with metrics and error tracking\n- **☁️ S3 Backup** — Optional write-through backup prevents cache eviction data loss\n\n## Quick Start\n\n### What You Need\n\n- A GitHub repository where you have admin access\n- An [OpenCode](https://opencode.ai/) account with API credentials\n- Basic familiarity with GitHub Actions\n\n### Step 1: Configure Secrets\n\nAdd the following secret to your repository (Settings → Secrets and variables → Actions):\n\n**`OPENCODE_AUTH_JSON`** — Your LLM provider credentials in JSON format:\n\n```json\n{\n  \"anthropic\": {\"apiKey\": \"sk-ant-api-...\"},\n  \"openai\": {\"apiKey\": \"sk-...\"}\n}\n```\n\n### Step 2: Create Workflow File\n\nCreate `.github/workflows/fro-bot.yaml` in your repository:\n\n```yaml\nname: Fro Bot Agent\non:\n  issue_comment:\n    types: [created]\n\njobs:\n  agent:\n    # Only run when @fro-bot is mentioned\n    if: contains(github.event.comment.body, '@fro-bot')\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      issues: write\n      pull-requests: write\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: fro-bot/agent@v0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n```\n\n### Step 3: Mention the Agent\n\nComment `@fro-bot` on any issue or pull request. The agent will:\n\n1. Add a 👀 reaction to acknowledge your request\n2. Restore its memory from previous runs\n3. Execute the requested task using OpenCode\n4. Post a response with a run summary\n\n\u003e [!NOTE]\n\u003e\n\u003e On first run, the action automatically installs OpenCode — no manual setup required! If you need oMo agent workflows with Sisyphus or other oMo-provided agents, set `enable-omo: true` in your workflow.\n\n\u003e [!TIP]\n\u003e\n\u003e **Full workflow reference** — The Quick Start above covers a single trigger. For the complete workflow with all supported triggers, conditional token selection, scheduled tasks, and PR reviews, see [`docs/examples/fro-bot.yaml`](docs/examples/fro-bot.yaml).\n\u003e\n\u003e **AI-assisted setup** — To have an AI agent set up the workflow for your repository, point it at the example file and tell it to follow the instructions in the header:\n\u003e\n\u003e \u003e Fetch `https://raw.githubusercontent.com/fro-bot/agent/refs/heads/main/docs/examples/fro-bot.yaml` and follow the instructions at the top of the file to set up the Fro Bot agent workflow for this repository.\n\n## How It Works\n\nFro Bot uses a multi-phase execution model to provide stateful AI assistance:\n\n```mermaid\ngraph TB\n%% Brand Colors: Void=#0D0216, Purple=#1A0B2E, Cyan=#00BCD4, Magenta=#E91E63, Amber=#FFC107\n%% Nodes\nA[Trigger Event] --\u003e B[Restore Cache]\nB --\u003e C[Load Session History]\nC --\u003e D[Acknowledge Request]\nD --\u003e E[Execute Agent]\nE --\u003e F[Post Response]\nF --\u003e G[Save Session State]\nG --\u003e H[Update Cache]\n\n%% Styles\nclassDef default fill:#1A0B2E,stroke:#3D2A5F,stroke-width:1px,color:#FFFFFF\nclassDef start fill:#1A0B2E,stroke:#00BCD4,stroke-width:2px,color:#00BCD4\nclassDef action fill:#2D1B4E,stroke:#E91E63,stroke-width:2px,color:#FFFFFF\nclassDef endNode fill:#1A0B2E,stroke:#FFC107,stroke-width:2px,color:#FFC107\n\n%% Apply Styles\nclass A start\nclass E action\nclass H endNode\n\n%% Link Styles (explicit indexes for broad Mermaid compatibility)\nlinkStyle 0 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 1 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 2 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 3 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 4 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 5 stroke:#3D2A5F,stroke-width:2px\nlinkStyle 6 stroke:#3D2A5F,stroke-width:2px\n```\n\n### Execution Phases\n\n1. **Cache Restore** — Previous session state loaded from GitHub Actions cache (or S3 if configured)\n2. **Session Discovery** — Agent searches prior sessions for relevant context\n3. **Request Acknowledgment** — Visual feedback via reactions and labels\n4. **Agent Execution** — OpenCode runs with full access to conversation history\n5. **Response Publishing** — Results posted as comments or PR reviews\n6. **State Persistence** — Updated session data saved back to cache\n7. **Session Pruning** — Old sessions removed per retention policy\n\n### Cache Strategy\n\nSessions are cached using a branch-scoped key:\n\n```text\nopencode-storage-{repo}-{branch}-{os}\n```\n\nThis approach:\n\n- **Isolates branches** to prevent cache poisoning\n- **Preserves context** within feature branches\n- **Enables continuity** when working on long-running tasks\n\n\u003e [!WARNING] GitHub Actions cache has a 10GB limit per repository and entries expire after 7 days of inactivity. For mission-critical persistence, enable S3 backup.\n\n## Usage\n\n### Comment Triggers\n\nThe agent responds when mentioned in comments on issues, pull requests, or PR review threads:\n\n```markdown\n@fro-bot Can you investigate why the CI tests are failing?\n```\n\n```markdown\n@fro-bot Please review this PR and suggest improvements\n```\n\n```markdown\n@fro-bot What did we decide about error handling in the last discussion?\n```\n\n### Supported Events\n\n| Event | Trigger | Default Behavior |\n| --- | --- | --- |\n| `issue_comment` | `@fro-bot` mention | Respond to comment |\n| `issues` (opened/edited) | `@fro-bot` in issue body | Triage issue and propose next steps |\n| `pull_request` | PR opened/synced/reopened/ready_for_review/review_requested | Review code for quality and potential bugs |\n| `pull_request_review_comment` | `@fro-bot` in review thread | Respond to specific code review comment |\n| `workflow_dispatch` | Manual workflow trigger | Execute custom prompt (required input) |\n| `schedule` | Cron schedule | Execute periodic task (requires prompt config) |\n\n### Access Control\n\nFor security, the agent only responds to trusted users:\n\n- **Repository owners**\n- **Organization members**\n- **External collaborators**\n\nBot accounts and first-time contributors from forks are automatically skipped to prevent abuse.\n\n## Event Trigger Reference\n\nThe action supports seven event types. Use this section to wire triggers correctly and understand prompt, permissions, and concurrency expectations.\n\n| Event | Actions | @mention required | Prompt source | Minimum permissions | Concurrency key |\n| --- | --- | --- | --- | --- | --- |\n| `issue_comment` | `created` | Yes | Comment body | `contents: read`, `issues: write`, `pull-requests: write` | `issue.number` or `run_id` |\n| `pull_request_review_comment` | `created` | Yes | Comment body | `contents: read`, `pull-requests: write` | `pull_request.number` or `run_id` |\n| `discussion_comment` | `created` | Yes | Comment body | `contents: read`, `discussions: write` | `discussion.number` or `run_id` |\n| `issues` | `opened`, `edited` | No (opened), Yes (edited) | Built-in directives | `contents: read`, `issues: write` | `issue.number` or `run_id` |\n| `pull_request` | `opened`, `synchronize`, `reopened`, `ready_for_review`, `review_requested` | No | `prompt` input (review prompt) | `contents: read`, `pull-requests: write` | `pull_request.number` or `run_id` |\n| `schedule` | Cron | No | `prompt` input (schedule prompt) | `contents: read`, `issues: write` | `run_id` |\n| `workflow_dispatch` | Manual | No | `prompt` input (required) | Varies by task | `run_id` |\n\n### Trigger Details\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eissue_comment\u003c/strong\u003e — comment mentions in issues and PRs\u003c/summary\u003e\n\n- **Behavior:** Responds to comments with `@fro-bot`.\n- **Skip conditions:** Bot comments, missing mention, or author association not in `OWNER`, `MEMBER`, `COLLABORATOR`.\n- **Guard example:**\n  ```yaml\n  if: \u003e-\n    (github.event.pull_request == null || !github.event.pull_request.head.repo.fork) \u0026\u0026 github.event_name == 'issue_comment' \u0026\u0026 contains(github.event.comment.body || '', '@fro-bot') \u0026\u0026 (github.event.comment.user.login || '') != 'fro-bot' \u0026\u0026 contains(fromJSON('[\"OWNER\", \"MEMBER\", \"COLLABORATOR\"]'), github.event.comment.author_association || '')\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003epull_request_review_comment\u003c/strong\u003e — review thread mentions\u003c/summary\u003e\n\n- **Behavior:** Responds to `@fro-bot` mentions inside PR review threads.\n- **Skip conditions:** Same gating as `issue_comment` (mention + association + bot check).\n- **Guard example:**\n  ```yaml\n  if: \u003e-\n    (github.event.pull_request == null || !github.event.pull_request.head.repo.fork) \u0026\u0026 github.event_name == 'pull_request_review_comment' \u0026\u0026 contains(github.event.comment.body || '', '@fro-bot') \u0026\u0026 (github.event.comment.user.login || '') != 'fro-bot' \u0026\u0026 contains(fromJSON('[\"OWNER\", \"MEMBER\", \"COLLABORATOR\"]'), github.event.comment.author_association || '')\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003ediscussion_comment\u003c/strong\u003e — discussion mentions\u003c/summary\u003e\n\n- **Behavior:** Responds to `@fro-bot` mentions in discussion threads (if Discussions are enabled).\n- **Skip conditions:** Missing mention, bot comments, or untrusted author association.\n- **Guard example:**\n  ```yaml\n  if: \u003e-\n    github.event_name == 'discussion_comment' \u0026\u0026 contains(github.event.comment.body || '', '@fro-bot') \u0026\u0026 (github.event.comment.user.login || '') != 'fro-bot' \u0026\u0026 contains(fromJSON('[\"OWNER\", \"MEMBER\", \"COLLABORATOR\"]'), github.event.comment.author_association || '')\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eissues\u003c/strong\u003e — issue opened/edited\u003c/summary\u003e\n\n- **Behavior:** Auto-triage on `opened`. `edited` requires a mention.\n- **Skip conditions:** Locked issues, bot authors, or untrusted author association.\n- **Guard example:**\n  ```yaml\n  if: github.event_name == 'issues'\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003epull_request\u003c/strong\u003e — AI code review (not CI)\u003c/summary\u003e\n\n- **Behavior:** Runs an AI review on `opened`, `synchronize`, `reopened`, `ready_for_review`, and `review_requested`.\n- **Reviewer-assignment gating:** For `review_requested` and `ready_for_review`, processing continues only when the configured bot login is requested as reviewer (or when `bot-login` is not set).\n- **Team requests:** `review_requested` events targeting teams are normalized and exposed in context, but current gating only auto-triggers for explicit reviewer logins, not team membership expansion.\n- **Skip conditions:** Draft PRs and fork PRs. For `opened`/`synchronize`/`reopened`/`ready_for_review`, untrusted author association is skipped. For `review_requested`, processing is gated by requester bot-check and explicit bot reviewer assignment.\n- **Guard example:**\n  ```yaml\n  if: \u003e-\n    github.event_name == 'pull_request' \u0026\u0026 !github.event.pull_request.head.repo.fork\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eschedule\u003c/strong\u003e — periodic maintenance\u003c/summary\u003e\n\n- **Behavior:** Executes a scheduled prompt (must be provided via `prompt` input).\n- **Skip conditions:** Missing prompt (the action exits cleanly).\n- **Guard example:**\n  ```yaml\n  if: github.event_name == 'schedule'\n  ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eworkflow_dispatch\u003c/strong\u003e — manual prompt execution\u003c/summary\u003e\n\n- **Behavior:** Runs the user-supplied prompt.\n- **Skip conditions:** Missing prompt input when marked `required: true`.\n- **Guard example:**\n  ```yaml\n  if: github.event_name == 'workflow_dispatch'\n  ```\n\n\u003c/details\u003e\n\n### Permissions Guide\n\nUse the minimum permissions needed for the triggers you enable.\n\n```yaml\npermissions:\n  contents: read\n  issues: write\n  pull-requests: write\n  discussions: write\n```\n\n- `discussion_comment` requires `discussions: write`.\n- `issues` and `schedule` need `issues: write` to create or comment on issues.\n- `pull_request` reviews require `pull-requests: write`.\n\n### Concurrency Strategy\n\nUse a single concurrency group that scopes to the relevant issue/PR/discussion and falls back to the run ID for schedule/dispatch.\n\n```yaml\nconcurrency:\n  group: \u003e-\n    fro-bot-${{\n      github.event.issue.number ||\n      github.event.pull_request.number ||\n      github.event.discussion.number ||\n      github.run_id\n    }}\n\n\n  cancel-in-progress: false\n```\n\n### Security Model\n\n- **Association gating:** The router only processes events from `OWNER`, `MEMBER`, and `COLLABORATOR` users.\n- **Bot protection:** Bot comments are ignored to avoid loops.\n- **Fork protection:** `pull_request` runs are skipped for forks; comment triggers are still gated by association.\n- **Mention identity:** Mention-based triggers require a token whose login matches the `@` mention users type. Using `GITHUB_TOKEN` means the mention would be `@github-actions`, so `@fro-bot` requires a PAT or GitHub App token.\n\n## Configuration\n\n### Action Inputs\n\n| Input | Required | Default | Description |\n| --- | --- | --- | --- |\n| `github-token` | Yes | — | GitHub token with write permissions |\n| `auth-json` | Yes | — | JSON object mapping LLM providers to credentials |\n| `prompt` | No | — | Custom prompt for the agent |\n| `agent` | No | — | Agent to use. When unset, uses OpenCode's built-in `build` agent. Must be a primary agent, not a subagent. |\n| `enable-omo` | No | `false` | Enable Oh My OpenAgent for extended provider and agent support. When `true`, installs Bun and oMo, and oMo configures Sisyphus as the default agent. |\n| `enable-omo-slim` | No | `false` | Enable [OMO Slim](https://github.com/alvinunreal/oh-my-opencode-slim) orchestration. Mutually exclusive with `enable-omo`. When `true`, installs Bun and OMO Slim and pins `orchestrator` as the default agent. |\n| `omo-slim-preset` | No | `openai` | OMO Slim preset to install. One of `openai`, `opencode-go`. Only applies when `enable-omo-slim: true`. |\n| `model` | No | — | Model override in `provider/model` format |\n| `timeout` | No | `1800000` | Execution timeout in milliseconds (0 = no limit) |\n| `opencode-version` | No | `1.2.24` | OpenCode CLI version for installation |\n| `systematic-version` | No | `2.1.0` | Systematic plugin version for OpenCode |\n| `session-retention` | No | `50` | Number of sessions to retain before pruning |\n| `s3-backup` | No | `false` | Enable S3-compatible object storage as canonical backend |\n| `s3-bucket` | No | — | Bucket name (required if `s3-backup` is true) |\n| `aws-region` | No | — | Region for the bucket (e.g. `us-east-1`, `auto` for R2) |\n| `s3-endpoint` | No | — | Custom endpoint URL for non-AWS providers (R2, B2, MinIO) |\n| `s3-prefix` | No | `fro-bot-state` | Prefix for all object keys |\n| `s3-expected-bucket-owner` | No | — | AWS account ID for bucket ownership pinning |\n| `s3-allow-insecure-endpoint` | No | `false` | Allow HTTP endpoints (local MinIO dev only) |\n| `s3-sse-encryption` | No | auto | `aws:kms` or `AES256` (auto-picked by endpoint) |\n| `s3-sse-kms-key-id` | No | — | Customer-managed KMS key ID for SSE-KMS |\n| `skip-cache` | No | `false` | Skip cache restore (useful for debugging) |\n| `systematic-config` | No | — | Custom Systematic configuration JSON (deep-merged) |\n| `opencode-config` | No | — | Custom OpenCode configuration JSON (deep-merged) |\n\n\u003e [!IMPORTANT] **Migration: oMo default change.** Previous versions of this action shipped with Oh My OpenAgent enabled by default. As of this release, oMo is opt-in. If your workflow relies on oMo-provided agents (such as Sisyphus), set `enable-omo: true`. When oMo is disabled (the default):\n\u003e\n\u003e - `default_agent` in the generated OpenCode config is forced to `\"build\"`.\n\u003e - `oh-my-openagent` entries are stripped from both `plugin` and legacy `plugins` in any user-provided `opencode-config` (a warning names rewritten fields).\n\u003e - Both behaviors are bypassed when `enable-omo: true` — oMo manages its own config and agent selection.\n\n\u003e [!NOTE] **OMO Slim** is an alternative orchestration plugin to oMo and cannot run alongside it — enabling both `enable-omo` and `enable-omo-slim` fails fast. When `enable-omo-slim: true`, the action installs OMO Slim with the chosen `omo-slim-preset`, registers the `oh-my-opencode-slim` plugin, and pins `default_agent` to `\"orchestrator\"`. The gateway environment variable for OMO Slim presets in workspace containers is deferred until the workspace image runs OpenCode.\n\n### Action Outputs\n\n| Output         | Description                                       |\n| -------------- | ------------------------------------------------- |\n| `session-id`   | OpenCode session ID used for this run             |\n| `cache-status` | Cache restore status (`hit`, `miss`, `corrupted`) |\n| `duration`     | Run duration in seconds                           |\n\n### Secrets Configuration\n\n#### Required\n\n**`OPENCODE_AUTH_JSON`** — LLM provider credentials in JSON format:\n\n```json\n{\n  \"anthropic\": {\"apiKey\": \"sk-ant-...\"},\n  \"openai\": {\"apiKey\": \"sk-...\"}\n}\n```\n\nSupports any provider supported by OpenCode. See [OpenCode documentation](https://opencode.ai/docs/) for the complete list.\n\n#### Optional (for S3 backup)\n\n- `AWS_ACCESS_KEY_ID` — IAM user access key\n- `AWS_SECRET_ACCESS_KEY` — IAM user secret key\n\nThe IAM user needs `s3:PutObject` and `s3:GetObject` permissions for the configured bucket.\n\n## Advanced Examples\n\n### Scheduled Maintenance Tasks\n\nRun the agent daily to maintain a rolling maintenance report:\n\n```yaml\nname: Daily Maintenance Report\non:\n  schedule:\n    - cron: \"30 15 * * *\" # Daily at 15:30 UTC (8:30 AM Arizona)\n\njobs:\n  maintenance:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      issues: write\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: fro-bot/agent@v0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n          prompt: |\n            Perform daily repository maintenance and update a SINGLE rolling\n            issue titled \"Daily Maintenance Report\". Search for an existing\n            issue with this exact title; create it if none exists.\n            Append a dated \"## YYYY-MM-DD (UTC)\" section with:\n            - Summary metrics (new issues, open PRs, stale items)\n            - Stale issues (\u003e30 days) and PRs (\u003e7 days)\n            - Unassigned bugs and recommended actions\n            Do NOT comment on individual issues/PRs. Update ONE issue only.\n```\n\n\u003e [!TIP]\n\u003e\n\u003e The example above uses a read-only maintenance report. For an **autohealing** variant that actively fixes failing PRs, patches vulnerabilities, and upgrades dependencies, see the \"Schedule Prompt Alternatives\" section in [`docs/examples/fro-bot.yaml`](docs/examples/fro-bot.yaml).\n\n### Manual Workflow with Custom Prompt\n\nAllow team members to manually trigger the agent with custom instructions:\n\n```yaml\nname: Manual Agent Task\non:\n  workflow_dispatch:\n    inputs:\n      prompt:\n        description: What should the agent do?\n        required: true\n        type: string\n\njobs:\n  custom-task:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      issues: write\n      pull-requests: write\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: fro-bot/agent@v0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n          prompt: ${{ inputs.prompt }}\n```\n\n### Durable Object Storage\n\nEnable S3-compatible object storage as the canonical persistence backend. GitHub Actions cache acts as a hot accelerator; S3 is the source of truth and survives cache eviction.\n\nWhen enabled:\n\n1. Sessions, prompt artifacts, and run metadata are written to both cache and S3 on save\n2. Restore tries GitHub cache first (faster), falls back to S3 on miss/corruption\n3. S3 failures are logged but never fail the run\n\n#### AWS S3\n\n```yaml\n- uses: fro-bot/agent@v0\n  with:\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n    auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n    s3-backup: true\n    s3-bucket: my-agent-sessions\n    aws-region: us-east-1\n    s3-expected-bucket-owner: \"123456789012\"  # Your AWS account ID\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n```\n\n#### Cloudflare R2\n\n```yaml\n- uses: fro-bot/agent@v0\n  with:\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n    auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n    s3-backup: true\n    s3-bucket: my-agent-sessions\n    aws-region: auto\n    s3-endpoint: https://\u003caccount-id\u003e.r2.cloudflarestorage.com\n    s3-sse-encryption: AES256  # R2 does not support aws:kms\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}\n```\n\n#### Backblaze B2\n\n```yaml\n- uses: fro-bot/agent@v0\n  with:\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n    auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n    s3-backup: true\n    s3-bucket: my-agent-sessions\n    aws-region: us-west-004\n    s3-endpoint: https://s3.us-west-004.backblazeb2.com\n    s3-sse-encryption: AES256\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.B2_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.B2_APPLICATION_KEY }}\n```\n\n#### MinIO (local development only)\n\n```yaml\n- uses: fro-bot/agent@v0\n  with:\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n    auth-json: ${{ secrets.OPENCODE_AUTH_JSON }}\n    s3-backup: true\n    s3-bucket: agent-dev\n    aws-region: us-east-1\n    s3-endpoint: http://localhost:9000\n    s3-allow-insecure-endpoint: \"true\"  # Required for non-HTTPS endpoints\n    s3-sse-encryption: AES256\n  env:\n    AWS_ACCESS_KEY_ID: minioadmin\n    AWS_SECRET_ACCESS_KEY: minioadmin\n```\n\n#### Security Defaults\n\n- **SSE-KMS** for AWS S3 (auto-selected when no custom endpoint); **AES256** for custom endpoints (R2/B2/MinIO)\n- **HTTPS required** unless `s3-allow-insecure-endpoint: true` is explicitly set\n- **SSRF protection**: link-local, loopback, and private IP endpoints are rejected by default\n- **Path traversal protection** on downloads — malicious S3 keys cannot escape the local storage directory\n- **Fork-PR writes are disabled** — prevents attacker-controlled prompts from writing to the canonical store\n- **Credentials** must come from env vars or IAM roles; never from action inputs\n- **IAM policy** requires `s3:GetObject`, `s3:PutObject`, `s3:ListBucket` (with prefix condition); no `s3:DeleteObject` needed\n\n\u003e [!TIP]\n\u003e\n\u003e Durable object storage is recommended for production deployments where losing agent memory would significantly impact operations. The GitHub Actions cache remains a hot accelerator, so there is no latency penalty on cache hits.\n\n## Troubleshooting\n\n### Agent Not Responding\n\n- **Check permissions**: Verify your workflow has `contents`, `issues`, and `pull-requests` write permissions\n- **Verify secrets**: Ensure `OPENCODE_AUTH_JSON` is properly formatted JSON\n- **Check trigger condition**: For comment triggers, ensure `@fro-bot` appears in the comment\n- **Review access control**: Only repo owners, org members, and collaborators can trigger the agent\n\n### Cache Issues\n\nIf sessions aren't persisting between runs:\n\n1. Check GitHub Actions cache size (Settings → Actions → Cache)\n2. Enable S3 backup for more reliable persistence\n3. Verify `skip-cache` isn't set to `true`\n4. Review run logs for cache corruption warnings\n\n### Timeout Errors\n\nIf the agent times out before completing:\n\n- Increase `timeout` value (default is 30 minutes)\n- Check for infinite loops or stuck operations in logs\n- Consider breaking large tasks into smaller steps\n\n## Development\n\n### Prerequisites\n\n- Node.js 24 (see `.node-version`)\n- pnpm 10+\n\n### Setup\n\n```bash\n# Install dependencies\npnpm install\n\n# Run tests\npnpm test\n\n# Build action\npnpm build\n\n# Lint code\npnpm lint\n```\n\n### Project Structure\n\n```text\n├── src/\n│   ├── main.ts              # Main action entry point\n│   ├── post.ts              # Post-action cache save hook\n│   └── lib/\n│       ├── agent/           # OpenCode execution \u0026 prompts\n│       ├── attachments/     # File attachment processing\n│       ├── cache.ts         # GitHub Actions cache operations\n│       ├── comments/        # GitHub comment API interactions\n│       ├── github/          # GitHub API client \u0026 context\n│       ├── observability/   # Metrics \u0026 run summaries\n│       ├── reviews/         # PR review logic\n│       ├── session/         # Session management \u0026 search\n│       ├── setup/           # OpenCode/oMo installation\n│       └── triggers/        # Event routing \u0026 filtering\n├── dist/                    # Bundled output (committed)\n├── RFCs/                    # Architecture decision records\n└── action.yaml              # Action definition\n```\n\n### Testing\n\nThe project uses Vitest with comprehensive test coverage:\n\n```bash\n# Run all tests\npnpm test\n\n# Run specific test file\npnpm test src/lib/agent/prompt.test.ts\n\n# Watch mode (for development)\npnpm test --watch\n```\n\n### Contributing\n\nThis project follows test-driven development (TDD):\n\n1. Write failing test first\n2. Implement minimal code to pass\n3. Refactor while keeping tests green\n4. Never commit without running `pnpm build` (dist/ must stay in sync)\n\nSee `AGENTS.md` for detailed development guidelines and architecture overview.\n\n## References\n\n- [OpenCode Documentation](https://opencode.ai/docs/) — Official OpenCode platform docs\n- [Oh My OpenAgent (oMo)](https://github.com/code-yeongyu/oh-my-openagent) — Agent workflow framework\n- [GitHub Actions Documentation](https://docs.github.com/en/actions) — GitHub Actions reference\n- [Action Source Code](https://github.com/fro-bot/agent) — View the implementation\n\n## License\n\n[MIT](LICENSE) © Fro Bot\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffro-bot%2Fagent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffro-bot%2Fagent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffro-bot%2Fagent/lists"}