How-to

Goal-Driven Automation: Why Intentions Beat Instructions

The philosophical shift from scripting every step to specifying the outcome you want — and why it unlocks a completely different class of automation.

O
OpenHelm Team· Product
··8 min read

There are two ways to automate a task. You can write down every step required to complete it, or you can describe the outcome you want and let something else figure out the steps.

The first approach — scripting — has been the dominant paradigm for forty years. Shell scripts, Makefiles, CI pipelines, GitHub Actions workflows. All of them share the same fundamental model: you list what to do, in order, and the computer does it.

Scripting is powerful and predictable. It's also fundamentally limited: it can only do what you anticipated when you wrote the script.

Goal-driven automation is different. You describe the outcome. The system — in OpenHelm's case, Claude Code — figures out how to achieve it.

The Limits of Scripting

Consider a common developer task: upgrading a dependency. A script for this might look like:

  1. Run npm update package-name
  2. Run the test suite
  3. If tests pass, commit
  4. If tests fail, exit with error

That script handles the happy path. But what about the case where a test fails because the new version changed an API? The script can't read the error, reason about what changed, look up the new API in the changelog, and update the calling code. It just fails.

A goal like "upgrade lodash to the latest version and update any code that uses deprecated APIs" can handle that. Not because there's a special case written for it, but because the goal-executing system — Claude Code — can reason about the error and try something different.

Goals Are Not Prompts

Goal-driven automation is sometimes confused with "just using an LLM". It's more structured than that.

A good OpenHelm goal has:

  • An outcome statement — what success looks like
  • A project scope — which directory/repository to work in
  • A concrete acceptance criterion — how to know the goal is done (tests pass, PR opened, file exists)

These constraints aren't limitations — they're what makes goals safe to run unattended. Claude Code can iterate within the project scope, but it knows what "done" means.

When Goals Work Best

Goal-driven automation is most valuable for tasks that are:

  • Well-defined but not fully scripted — you know what you want, but the steps vary
  • Tolerant of iteration — it's fine if the first attempt fails and the system tries again
  • Reviewable by output — you can check a PR or a diff and verify correctness

Bad candidates: tasks where failure has irreversible consequences (database migrations without backups, deploys to production), tasks requiring human taste (design decisions), tasks requiring external context (talking to customers).

Good candidates: code improvements, documentation, test writing, dependency management, performance profiling, linting, scaffolding.

Writing Good Goals

The quality of your outcome statement matters. Here are some patterns that work well.

Be specific about the outcome, not the steps:

Good: "Add TypeScript strict mode to the project and fix all resulting type errors"
Bad:  "Run tsc --strict and fix errors"

Include acceptance criteria:

Good: "Write unit tests for the auth module until coverage reaches 80%"
Bad:  "Write unit tests for the auth module"

Bound the scope explicitly:

Good: "Refactor the database layer to use the new connection pool. Don't touch the API layer."
Bad:  "Refactor the database layer"

The Mental Shift

Switching from script-thinking to goal-thinking takes practice. The instinct is to break the task down into steps and write those down. Goal-thinking asks you to stop one level higher: what do you want to be true when this is done?

The answer to that question — stated clearly, scoped correctly, scheduled at the right time — is an OpenHelm goal. And when you wake up and it's done, the mental shift starts to feel obvious.

More from the blog