You have a prompt you paste into ChatGPT every Monday morning. It's three paragraphs long, you've edited it maybe forty times, and it still doesn't quite do what you want. That's not a prompt problem — it's a workflow problem wearing a prompt costume.
The gap between a useful prompt and a reliable agent is mostly a design gap. You haven't written down what your process actually is, in enough detail that a machine can repeat it without you watching. This post walks you through fixing that: capturing your real workflow, translating it into OpenClaw's file-based config layer, and testing it before you trust it with anything that matters.
If you want to design an OpenClaw agent from workflow rather than from vibes, this is the path.
Step 1: Write Down What You Actually Do
Before you open a config file, open a text editor. Describe your workflow in plain language — what triggers it, what happens in what order, and what "done" looks like.
For example: Every morning I check three RSS feeds, pull anything published in the last 24 hours that mentions competitors or pricing changes, summarize each item in two sentences, and drop the list into a Slack channel by 8 AM.
That paragraph contains everything you need: a trigger (time), inputs (RSS feeds), a filter (topic + recency), a transformation (summarize), and an output (Slack). Most workflows fit this shape once you write them out honestly.
Step 2: Identify the Variables and the Constants
Not every part of your workflow should be configurable. Some things never change — the Slack channel name, the summary format, the 8 AM deadline. Others might vary — the feeds you monitor, the keywords you care about this week.
Separate these before you touch a config file. Constants go into your agent's identity files. Variables belong in environment config or a runtime parameter the agent reads fresh each run.
This distinction saves you from the most common redesign headache: editing the wrong file at 7:45 AM because the agent hardcoded something it shouldn't have.
Step 3: Write Your SOUL.md
SOUL.md is where you define who your agent is: its purpose, its constraints, and its defaults when it hits ambiguity. Think of it as the agent's standing instructions — the things that should be true on every run, regardless of context.
For the RSS example above, your SOUL.md might read:
## Purpose
Monitor competitor RSS feeds daily and surface pricing or product changes.
## Tone
Neutral, factual. Two-sentence summaries only. No editorializing.
## Constraints
- Never post to Slack before 7:50 AM or after 8:15 AM.
- If no relevant items are found, post a single line: "No relevant updates today."
- Do not summarize items older than 24 hours.
## Escalation
If a feed is unreachable, log the error and continue with available feeds.
Do not skip the Slack post.
Notice: constraints are specific and testable. "Be professional" is useless. "Two-sentence summaries only" is not.
For a deeper look at why explicit constraints in identity files outperform prompt-based instructions, see Why File-Based Agent Configs Beat Black-Box AI Builders.
Step 4: Build Your AGENTS.md
AGENTS.md maps your workflow steps to specific agent behaviors and tool calls. Where SOUL.md defines values and guardrails, AGENTS.md defines execution.
For each step in your written workflow, create a named block:
## fetch_feeds
- Tool: rss_reader
- Inputs: feed_urls (from env), lookback_hours: 24
- Output: raw_items[]
## filter_items
- Filter raw_items where content matches any of: keywords[] (from env)
- Output: filtered_items[]
## summarize_items
- For each item in filtered_items:
- Summarize in exactly two sentences
- Include: source name, headline, publish time
- Output: summary_list[]
## post_to_slack
- Tool: slack_post
- Channel: #competitive-intel
- Message: formatted summary_list
- On empty list: post "No relevant updates today."
This format makes the execution path readable by you, auditable by a teammate, and interpretable by the runtime. That's the whole point of file-based agent configs.
Step 5: Schedule It With HEARTBEAT.md
HEARTBEAT.md is your scheduling and recurrence layer. It answers: when does this run, how often, and under what conditions?
HEARTBEAT.md workflow scheduling keeps your agent on a clock without you babysitting it. A minimal example:
## schedule
cron: "0 7 50 * * MON-FRI"
timezone: America/New_York
## retry
max_attempts: 2
backoff_seconds: 60
## health_check
ping_url: https://your-health-endpoint.example.com/ping
on_failure: log_and_continue
Keep your HEARTBEAT entries conservative at first. A missed run is better than a runaway one. If you're building something more complex — say, a nightly memory consolidation job — check out how AutoDream handles nightly memory consolidation for a model to follow.
Step 6: Map Prompts to Agent Steps
If you already have a working prompt, don't throw it away — decompose it. Read through it and find the implicit steps.
A prompt like *