← all postslights offlights on
Clicky, a paperclip mascot with glasses, a star head and a gear

// engineering --post 2026-09-15

Clicky: our software factory

Author line up:
  • Ben Wood, CTO of ClickFunnels
  • Nate Vick, VP of Platform Engineering
  • Rich Steinmetz, Staff Software Engineer
  • Clicky also had some say in it

We already had coding agents. What we didn't have was one that the company could run.

Clicky is the internal system ClickFunnels engineers use to get code written, tested, reviewed, and merged. You can ask it for a change from Slack, from a comment on a GitHub PR, from the terminal, or from Claude Code over MCP (Model Context Protocol), and it comes back with a pull request. It also picks up work on its own: Honeybadger errors, Dependabot alerts, failing CI on its own PRs, and scheduled jobs. It runs QA in Chrome and reviews PRs with a panel of three models.

In practice, people have started more PRs with Clicky than any other contributor individually over the last two months, and most of them started in a Slack thread with non-engineers.

How a task runs

An engineer asks for a change. Clicky creates a task and dispatches it to RWX, the CI platform we already use. RWX boots a worker with the repository cloned and a Claude Code agent running. The agent connects back to Clicky's Rails app over a WebSocket using the Agent Client Protocol, an open protocol for driving coding agents, and Clicky sends it the prompt.

The agent's output streams to the task page and, when the request came from Slack, to that thread. When the agent stops, a supervisor model reads the transcript and decides one of three things: the task is done, the agent needs another instruction, or a human needs to answer a question. If it is done, Clicky records the pull request and starts tracking it. If it needs another instruction, the supervisor writes one and the agent continues in the same session. If there is a question, Clicky posts it where the task came from, and the answer goes back into the same session. The task owner can also steer a running agent with a message at any point.

The agent process stays alive for the whole task, so a supervisor instruction, a human answer, or a steer goes to the running agent rather than a fresh one. When the task ends, the process exits, but the agent's session transcript is kept, and the next task in the same project (Clicky's grouping for related tasks in a repo) resumes it.

Environments

The worker and the application environment are separate. Most of a coding task is reading and editing files, which does not need Postgres or a running Rails server, so the worker does not start them. When the agent needs to run tests, seed data, or serve the app for QA, it starts an RWX sandbox from the repository's own .rwx/sandbox.yml and runs commands in it with rwx sandbox exec. RWX caches the layers that built the environment, so the sandbox is up in seconds.

The repository owns its environment definition. A repo that wants Clicky to run its tests ships a sandbox file and a short skill that tells the agent how to use the sandbox. For QA, the worker and the sandbox join a private network so the browser in the worker can reach the app in the sandbox.

We built on RWX because of how it models a run. A run is a DAG (Directed Acyclic Graph) of steps. Each step runs in its own VM and snapshots its filesystem, downstream steps start from those snapshots, and cache keys are computed from a step's inputs, so the same inputs always hit. Everything the worker needs, from Claude Code and the GitHub CLI to Chrome and the CLIs for the review panel's models, is installed by a cached upstream step. Only the steps that have to be fresh, such as fetching credentials and cloning the branch, run on each dispatch. Sandboxes share that cache and runtime, so the application environment starts from layers CI has already built.

Identity

Engineers own the software they ship, and Clicky is built around that. It acts on an engineer's behalf, under that engineer's identity, rather than as a shared bot account. Every agent turn has an owner. When a person asked for the work, the owner is the person whose message the agent is answering. Commits carry that person's name, pull requests open under their GitHub account, and the Linear and Honeybadger accounts the agent uses are the ones they linked in Clicky's web app. In a Slack thread where several people are asking for things, ownership changes turn by turn, so Clicky always knows who asked for what and whose access it is using.

Work with no human origin runs as Clicky's own user, which has its own GitHub account. Tasks started by a Dependabot alert, a Honeybadger fault, a failing check on a tracked PR, or an automation rule wired to a GitHub event all run as that user. Repository access is checked against the owner's GitHub permissions on every task and on every scheduled run.

Autonomous work

Dependabot. When Dependabot raises an alert, Clicky reads the advisory, checks where we use the affected code, regenerates the lockfile with the package manager, runs the relevant tests, and opens a PR with a severity table, an exposure analysis, and a confidence score. A human merges it.

Honeybadger. A new fault in a Honeybadger project Clicky monitors becomes a task. The agent pulls the error with the hb CLI, finds the raise site, fixes it, runs the tests, and opens a PR with the Honeybadger link. When Honeybadger reports an error-rate spike, a task reads the recent notices and posts a verdict to the Slack alerts channel.

Its own PRs. Every PR Clicky opens is tracked until it merges. If CI fails or the base branch moves and creates a conflict, Clicky spawns a fix task on that branch. Each PR gets a fixed number of attempts. After that, Clicky comments on the PR and, if a person started the task, DMs them. A human can reset the counter.

Schedules. Any task can run on a cron schedule as a one-time or recurring task. For example, our nightly Dependabot alert sweep opens a PR to clear our alerts.

Support. Clicky assigns incoming support tickets in Linear to an engineer based on current load, time zone, PTO, and routing rules the team writes.

Verification

QA. Mark a task for QA and the implementing agent writes a plain-English test plan and seeds the data it needs. A separate computer-use agent boots Chrome on a virtual display in the worker, works through the plan against the app in the sandbox, and posts a screenshot for every step, a video, and a pass or fail per scenario to the PR. An API mode runs against an OpenAPI spec without a browser.

Panel review. Request Clicky's review on a PR and three models from three vendors review the diff independently. Where they disagree, the agent running the panel checks the finding against the code. Clicky then posts one review: an approval or a request for changes. The rules are enforced in the Rails app, not in the prompt: all three models must report, every finding must include a fix, the verdict must match the findings, and the review is refused if the PR head has moved since the panel read the diff. Ask Clicky to address the findings and it re-checks each one, fixes the ones that hold, and replies on the ones that do not.

Integrations

Where you reach it: Slack, GitHub PR comments and review requests, a CLI, a REST API, an MCP server for Claude Code and other clients, Linear labels, and a web app.

What it connects to: GitHub, Linear, Honeybadger, the ClickFunnels product through ClickFunnels' own MCP server, LaunchDarkly, Loom, web search, Slack search and canvases, and read-only database views with PII and secrets redacted.

What changed for us

Before Clicky, engineers here were already using Claude Code for the core of what this post describes: writing the change, running the tests, and opening the PR. But each of us did it alone. The agent ran on one engineer's laptop, in a setup they had assembled themselves, in a session nobody else could see. Nothing ran unless someone started it, and when the session ended, whatever the agent had worked out ended with it.

Clicky moved the agent off the laptop and into the company's infrastructure. Every run is a task with an owner, a page anyone on the team can open, a transcript that is kept, and, when it came from Slack, a thread other people can join. The environment definition and the skills that tell the agent how to use it live in the repository, so every run starts from the same place. Events start work without anyone at a keyboard, and the work continues whether or not anyone is watching.

What changed is who the agent belongs to. A coding agent in an editor is a tool one engineer uses. Clicky is a system the team operates together. It produces changes continuously, and the engineers decide what it should work on and whether what it produced should ship.

$ build_with_us --submit

Building something? Share your use case.

Webhooks, API integrations, funnel automation: share what you are building with the Funnel Coders Discord community and get support from ClickFunnels engineers.

Share your use case

// engineering --post 2026-09-15 · all posts