Skip to content

feat(cloudflare): run a Fold coding agent on GitHub mentions - #19

Merged
K-Mistele merged 20 commits into
mainfrom
integrate-fold-github-agent-with-effect-channels-flepks
Oct 9, 2026
Merged

K-Mistele merged 20 commits into
mainfrom
integrate-fold-github-agent-with-effect-channels-flepks

Conversation

@K-Mistele

Copy link
Copy Markdown
Contributor

What this does

A maintainer's mention of the GitHub App on an issue or pull request now starts a Fold coding agent for that discussion, running in a Cloudflare Computer container with the repository cloned.

  • Mentions: the mention gets eyes, the discussion is followed, and the delivery is handed off to the discussion's AgentSession Durable Object. The turn runs in the background and reports through the delivery API, which posts the answer and removes eyes. Mentions in already-followed threads now run the mention callback (GitHub, Slack, Linear).
  • Context: each request starts with the discussion: all of it the first time, then only what is new, tracked by comment, review, and line comment IDs.
  • Branches: an issue works on humanlayer/issue-<n> and can open its pull request (github_create_pull_request, with Closes #<n>); a pull request works on its own branch. Git uses the App's installation token per request, shared with the API through one token cache (GitHubAppCredentials, GitHubGitCredentials). Fork pull requests fail with a clear message.
  • Tools: Fold's file, bash, web, and skill tools, update_plan (a checklist comment), git fetch/pull/merge/push, and GitHub tools to read the discussion, reviews, line comments, and checks, and to post or reply in a review thread.
  • Model: OpenAI gpt-6.1-sol at medium reasoning (OPENAI_API_KEY). Workers AI still labels new issues and pull requests, now at a 0.7 threshold, with scores logged as text.
  • GitHub package: pull request info includes the head repository; new listPullRequestsForBranch and createPullRequest operations.
  • Delivery: callback sequences execute in order across backends.
  • The GitHub debounce is 3 seconds.

The example README's new "The GitHub agent" section describes the behavior, branches, tools, and logs.

Tested

  • Unit and integration tests across the packages and the example (bun run test), typecheck, and lint.
  • Live on humanlayer/fold: mentions, eyes, issue branch creation and push, plan comments, discussion context, and answers. Pull request branches, github_create_pull_request, and review-thread replies are covered by tests but not yet tried live.

Not done

Check failure diagnostics and reacting to failing checks; existing lint warnings in tests (strict-effect-provide) and a few no-underscore-dangle/consistent-return warnings.

🤖 Generated with Claude Code

K-Mistele and others added 18 commits October 6, 2026 18:16
Persist callback progress and isolate each step's delivery identity so completed callbacks are not repeated on retries. Run GitHub creation before mention or subscription continuation, waiting for handoffs and output to settle before advancing.

Update all providers and storage backends with lifecycle contract coverage, and expose ready-to-use Cloudflare fetch handlers.

HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a10dfa-79aa-7107-94da-33b4cbb5e357
React with eyes for users with write access or higher. Deny other mentions with thumbs down and one bot-authored maintainer-only notice per issue or pull request, returning before authorized handlers run.

Exercise the registered mention handler, remove obsolete author-access and fake-agent code, and simplify the GitHub-only Worker setup.

HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a10dfa-79aa-7107-94da-33b4cbb5e357
The mention callback subscribes the discussion, sends the prompt and the
delivery's ID and token to the discussion's AgentSession, and hands the
delivery off once AgentSession accepts it.

AgentSession saves the delivery in its Durable Object storage, runs the
Fold turn in the background, and reports Working, then complete or fail,
through the Worker's delivery API over a self service binding. A retried
callback starts no second turn, and after a restart the saved delivery
lets recovery finish the right one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
Encode GitHub tool results through their schemas, build workspace file
errors in one place, move the Workers types reference into tsconfig, and
give the Cloudflare package tests the mailbox services Alchemy supplies to
a deployed Durable Object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
Alchemy gives a Durable Object's methods only the Worker's services, so the
mailbox alarm failed every GitHub event with "Service not found:
MailboxSubscriptions". The mailbox now captures its subscriptions when it is
built and provides them to the alarm. The tests now mirror how Alchemy calls
the alarm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
- Run one Fold session per turn, with services taken from the environment
  and layers provided once on the AgentSession's setup.
- Pull the latest commits before each new mention.
- Add web_search and web_fetch.
- Add update_plan, which puts the delivery API's whole DeliveryPlan on the
  active delivery; GitHub shows it as one edited comment.
- Start from Fold Agent's coding prompt, and save long bash output under
  /workspace/.fold/tool-output through its output store.
- Share one installation-token cache between the GitHub API and git
  (GitHubAppCredentials, GitHubGitCredentials). Clone, fetch, pull, and
  push send the token as a header per request, never stored or shown.
- Work on humanlayer/issue-<number>: check it out from GitHub when it
  exists, otherwise create it from the default branch and push it. Add
  git_fetch, git_pull, git_merge, and git_push tools.
- Say what went wrong in the failure comment, and log each turn's steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
…hreads

A comment that mentioned the bot in an already-subscribed GitHub issue or pull
request, or Slack thread, went to the subscribed-events callback, so the
mention callback (access check, activity, agent handoff) never ran again
after the first mention. A batch that mentions the bot now runs onMentioned /
onNewMention when it is configured; other batches in a subscribed discussion
still run the subscribed-events callback. Linear already worked this way.

Document the rule in the root and provider READMEs, and fix the example
README's handler path and follow-up check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
Fold 0.1.33 returns a tool call with bad params to the model as a failed
tool result instead of ending the run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
…ussion

The agent now runs on OpenAI's gpt-6.1-sol at medium reasoning, with
OPENAI_API_KEY bound as a secret. Workers AI still labels new issues and
pull requests.

Each request starts with the discussion: the issue or pull request and
everything said on it the first time, then only what is new since the
agent's last turn, tracked by the highest comment, review, and line
comment IDs it has seen. The bot's own comments and the comment that
mentioned it are left out. Pull requests get tools for reviews and line
comments, and the prompt asks the agent to answer questions quickly and
plan longer work first.

Tools that take no input used Schema.Struct({}), which accepts any value
but null, so OpenAI rejected them. They now use an object schema with no
fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
…s from issues

A pull request session now checks out the pull request's own branch, pulls
it on every mention, and can push to it. A pull request from a fork, or
whose branch was deleted, fails with a message saying why.

An issue session gets github_create_pull_request, which opens a pull
request from its branch into the default branch with "Closes #<number>",
or returns the one already open from that branch.

The GitHub package adds the head repository to pull request info, and
listPullRequestsForBranch and createPullRequest operations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
…t failure reasons

The prompt asks the agent to lead with the answer, size it to the
question, use plain words, skip narrating what it checked, and link to
the code on GitHub instead of explaining it at length.

Auto-labeling adds a label at a score of 0.7 or more, down from 0.8, and
logs the scores and label lists as text so they show in the Worker logs.
Failed git pulls and Computer git calls log their reason as text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
…ocument it

github_post_comment takes an optional reply_to on pull requests: the ID of
any line comment in a review thread, which it replies under the thread's
first comment. The agent is told its final answer is posted for it.

The comment and line comment tools return each comment's ID, author,
link, and text, plus the file, line, diff, and thread for line comments,
and the discussion context shows the same IDs. A mention in a line
comment tells the agent where the comment is and which thread to reply
in.

The example README describes the GitHub agent: what happens on a
mention, its branches, its tools, and what to look for in the logs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
@humanlayer-channels-app humanlayer-channels-app Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Oct 9, 2026
K-Mistele and others added 2 commits October 9, 2026 11:56
Emptiness checks use Effect's Array helpers, as typed lint requires.

The release script adds `^` only to a peer dependency that is a version,
so the preview Alchemy URL stays a valid peer range. The Durable Object
mailbox storage layer has a named type, so the published types no longer
import `alchemy/Cloudflare/index`, a path Alchemy does not export.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
A catalog entry that is a URL, like the Alchemy preview build, becomes `^`
and the version the package was built against, so npm can resolve it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a1196a-ea93-79e6-9500-a2651678f1ea
@K-Mistele
K-Mistele merged commit 91ed2ff into main Oct 9, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant