Open decisions: an agent that asks instead of guessing and follows up until you answer
The agent asks when a load-bearing fact is missing, files the question, and follows up on an age ladder until you decide.
Operations, intermediate. Published
What it does
The agent searches your notes, tasks and repository before it asks anything. If the missing fact is nowhere and it changes a decision, the agent asks directly, at the top of its reply, with options to pick from and the consequence of no answer. An unanswered question goes into a decision ledger under a stable key. Each morning and evening the agent shows at most three items: fresh ones in one line, older ones with their age, from day eight with the thing they block, from day fifteen as a choice between doing it and killing it. Before every follow-up the agent checks the source to confirm the item is still open.
When to use it
When to use it
- An agent works for you every day and makes calls based on facts about your business.
- Questions for you get lost in chat or in a list nobody reads.
- The agent fills in plausible-looking numbers it never checked.
- You have a morning or evening summary and want a short decision block in it.
When not to use it
- A one-off task with no later sessions: the ledger and the ladder never get time to work.
- The agent has no sources it can search, so every question would be blind.
- You only want a question gate before risky work starts: the clarify-before-acting template fits that better.
Decision table
| Situation | What the skill does |
|---|---|
| The missing fact is in your notes or tasks | The agent finds it and does not ask |
| The missing fact does not change a decision | The agent states its assumption in one line and keeps working |
| The missing fact changes a decision | The agent asks at the top of its reply, with options and the consequence |
| A question has waited 8-14 days | The agent names what it blocks or proposes dropping it |
| A question has waited 15 days or more | The agent offers two options, do it or kill it, with a recommendation |
Template
The method: when the agent asks, how it asks, how it files open questions and how it escalates them by age.
---
name: ask-and-push
description: Turns every load-bearing unknown into an explicit question instead of a guess, files unanswered questions in a decision ledger, and escalates them on a fixed age ladder until they are answered, deferred or killed. Use it whenever a fact you cannot find would change a decision, and whenever you write a morning or evening summary for the person you work for.
---
# Ask when unknown, push when unanswered
Read `CONTEXT.md` next to this file before you start. It names the person you ask (the decider),
where you search, where open decisions live, and when the two daily surfaces run.
If `CONTEXT.md` is missing, or a field you need is still blank, do not guess it. Ask the decider
to fill it, in the language they write to you in, naming the field. For example, in English:
"Add where I should file open decisions: DECISIONS.md in this folder, or a GitHub repository and label."
In Polish: „Dodaj, gdzie mam zapisywać otwarte decyzje: plik DECISIONS.md w tym folderze albo repozytorium GitHub i etykieta.”
## Before you start / What you need
- **An AI coding agent (required).** Claude Code (https://code.claude.com/docs/en/overview),
Codex CLI (https://developers.openai.com/codex/cli) or Cursor (https://cursor.com/docs),
with read and write access to the folder that holds the ledger.
- **A decision ledger (required, nothing to install by default).** The `DECISIONS.template.md`
that ships with this skill, copied to `DECISIONS.md`. If you prefer a public tracker, use
GitHub Issues through the GitHub CLI (https://cli.github.com/, MIT licence): sign in with
`gh auth login` in your own terminal, create a label with `gh label create decide`, file with
`gh issue create --label decide` (key in the title), and list with `gh issue list --label decide`.
- **One place for access keys (optional, pick one).**
1Password CLI (https://developer.1password.com/docs/cli/get-started/),
Bitwarden CLI (https://bitwarden.com/help/cli/), or a `.env` file listed in `.gitignore`
(https://git-scm.com/docs/gitignore). Write only the store's name or the file path in
`CONTEXT.md`, never a value.
Give the agent its own scoped access, never your whole vault. A personal sign-in reaches every
vault you own, so a separate vault on its own limits nothing:
- 1Password: create a vault that holds only this agent's keys, then a service account with read
access to that one vault (https://developer.1password.com/docs/service-accounts/). Put the
service account's token into the agent's shell environment yourself, under the variable name
the 1Password docs give, and never sign that shell in with your personal account. On the
agent's machine, turn off the desktop app's CLI integration, or never approve a 1Password
prompt raised from the agent's terminal.
- Bitwarden: create a separate Bitwarden account that holds only this agent's keys, and sign the
agent's shell in with that account only. Point the agent's `bw` at its own data directory (the
app data setting in the Bitwarden CLI docs), so your own login is never present there. Teams can use Bitwarden's machine-account CLI (bws),
scoped to one project, instead.
- A `.env` file: a separate file that holds only this agent's keys, listed in `.gitignore`.
Never paste a key, token or password into the chat, and never print one. That includes the two
login tokens in the agent's environment: the 1Password service account token and the Bitwarden
session key. The agent passes a key
straight into the command that needs it:
- 1Password: `op run --env-file=agent.env -- <command>`, where `agent.env` holds only
`op://vault/item/field` references, never values. `op run` masks the values it resolves.
- Bitwarden: `my_key="$(bw get password <item>)" <command>` as one command, never `bw get` on its
own. The command reads `my_key` from its environment. This form has no masking: never run it
with `-v`, `--verbose`, debug or trace flags, never use `set -x`, and never echo the variable.
- A `.env` file: let the tool that needs it load it, never `cat` it or show it in the reply.
To check that a key exists, look for its name only: `op item list --vault <vault>` (titles only),
`bw get item <item> >/dev/null 2>&1 && echo found` (never without the redirect), or
`grep -cE '^(export )?my_key=' .env`.
This skill fixes two failures with one root cause: treating "I don't know" as something to route
around instead of something to say.
- **The guess.** A missing fact gets filled with the most plausible value and shipped as if
verified. When the fact concerns money, legal standing or a number the decider will
repeat in public, a wrong plausible answer does more damage than no answer, because it looks
verified.
- **The decay.** A question that does get asked lands in a list and sits there. A list nobody
reads is storage, not escalation.
---
## PART 1: ASK
### 1. Search first, always
Never ask what searching would answer. Before any fact becomes a question, work through every
source listed under "Where to search" in `CONTEXT.md`: notes, the task tracker, logs, the
codebase, connected tools. Make at least three distinct search attempts. For a credential, check
every credential store listed in `CONTEXT.md` before raising it. If it is not there, ask the
decider where it lives or to provide it. Never print a credential value (check by name only, and
pass it into the command that needs it as shown in "Before you start"). Never invent a credential, and never store one in a
file, a ledger row or `CONTEXT.md`.
Only what survives the search may become a question. When you ask, name what you searched:
"Searched the notes folder, the tracker and the repo; the value is not recorded anywhere."
### 2. Sub-agents ask you, not the decider
If you orchestrate other agents, their questions come to you first. Answer them from the original
task prompt, the standing decisions in `CONTEXT.md`, or a source you can read. Only a question
that survives that pass goes to the decider, and it goes through you, grouped with the others,
never as a stream from each agent.
### 3. Is the fact load-bearing?
A fact is load-bearing if **any** of these holds:
| Test | Example |
|---|---|
| Getting it wrong changes a decision the decider would act on | which of two landing pages a promotion runs on |
| It is a number the decider would act on, repeat or publish | a conversion rate quoted in a newsletter |
| It is an unverifiable claim about their business, money, legal standing or compliance | which supplier invoice a refund belongs to |
| It selects between two or more materially different outputs | is this a supplier price-change notice or a customer apology email |
| Only their preference or authority can settle it | approve the default, or name the option to discuss |
If none holds, the gap is not load-bearing. State your assumption in one line and keep working.
Do not ask.
### 4. Banned substitutes
When a load-bearing fact is missing, each of these is a violation:
- A plausible value presented without a flag ("your list gets about a thousand opens per send").
- A silent assumption that never appears in your reply.
- `no data`, `TBD`, `unknown` or `n/a` sitting in a table cell or mid-report where the reader
scrolls past it.
- Hedged prose that implies the fact while disclaiming it ("presumably around...", "likely the...").
- Deferring the question to a later session, a file or another agent instead of asking now.
### 5. How to ask
- **Placement.** Put the question at the top of the reply, or in the same paragraph as the
conclusion it undermines. Never below the fold, never only inside a linked file.
- **Shape.** Binary or multiple choice beats open-ended: "The spring sale or the summer
sale?" instead of "Which sale?"
- **Consequence named.** Every question says what it blocks or what you will assume without it:
"Without this, the refund stays unmatched in the month-end check."
- **Rank, then ask the few that block most.** Order the open unknowns by what each one stops and
raise only the top few (see `CONTEXT.md`, default 3). Everything below the line goes to the
ledger, not into the reply.
- **Ask and keep working.** Unless the question truly blocks all progress, state your working
assumption and carry on. The question and the work ship together.
### 6. Every unanswered ask becomes a ledger item
If a load-bearing question is not answered in the same session, file it in the decision ledger
named in `CONTEXT.md` before the session ends. The ledger can be any task list, an issue tracker
or the plain `DECISIONS.md` that ships with this skill. Each item carries:
- **key**: a stable, normalised identity for the underlying question, for example
`ask:shop:checkout-provider`. Add a date only when the question itself is date-specific.
- **question**: one sentence, answerable as written.
- **opened**: the date you filed it.
- **origin date**: the date the question first arose, if earlier than `opened`.
- **blocks**: the concrete thing waiting on the answer (a task ID, a file, a named deliverable).
- **options**: the choices, with your recommendation marked.
- **status**: `decide`, `scheduled` (deferred), `done` or `dropped`.
- **deferred until**: for a `scheduled` item, the date it may be raised again. Empty otherwise.
- **last pushed**: the date and surface where you last raised it.
Before filing, search the ledger for both the key and the question text. One question, one row.
An unknown that is asked and then dropped is the same failure as never asking.
---
## PART 2: PUSH
### 7. The age ladder
Compute age from the item's `opened` date, unless the item's `origin date` (or its text) names an
earlier date. The older date sets the band. A re-filed item otherwise looks younger than it is.
| Age | Band | Treatment |
|---|---|---|
| 0-3 days | **Listed** | One line in the decision block. No commentary. |
| 4-7 days | **Re-raised** | Named with its age: "Open 5 days." Stated as still waiting, not re-explained. |
| 8-14 days | **Blocking-named** | Placed above younger items and must name the concrete thing it blocks. If nothing is blocked, that is the finding: propose dropping it. |
| 15+ days | **Forced disposition** | "Kill it or do it." Exactly two options and a recommendation, repeated at the top of both daily surfaces until it leaves `decide`. |
From day 8, "still open" is not a push. A push says what stopped moving because the answer is
missing. If you cannot name a downstream item, write: "Nothing is waiting on this. Drop it?"
### 8. Critical incidents bypass age
An item marked as a critical incident (the marker is defined in `CONTEXT.md`, for example
severity set to critical plus an incident label) is pushed from day 0, ahead of the age ladder.
Lead with containment status, then the exact decision the decider has to make now. A scary word
in the title does not make an incident; only the marker does. Keep critical incidents to at most
two slots per surface.
### 9. Two surfaces, every day
Run the ladder on two surfaces, at the times in `CONTEXT.md`:
- **Morning summary.** Sets the day's cycle. Pick the top items by band.
- **Evening summary.** Runs the ladder again but shows only items that became eligible today,
items whose band advanced today, and every 15+ day item. Do not replay a younger, unchanged
item already pushed that morning.
Update each item's `last pushed` field when you raise it.
---
## PART 3: ANTI-NAG GUARD
A channel that fires on everything gets tuned out, and then nothing gets pushed. This guard is
part of the method, not a softening of it.
### 10. Cap and shape
- **At most 3 items per surface** (morning, evening, and per working session outside them). The
ladder selects; it never enumerates the whole ledger.
- **Selection order:** critical incidents, then 15+, then 8-14, then 4-7, then 0-3. Within a
band, oldest first. Spread across areas when two items tie.
- **One labelled block.** Render the selected items in one block titled "decisions waiting",
each with its area visible. Do not scatter pushes through a reply or re-argue them mid-answer.
One block, then back to the work.
- For a full audit, list the whole ledger, but label it as diagnostic and never let that list
feed a push surface or update `last pushed`.
### 11. Deferral and kill are real answers
- **Deferral.** When the decider says "not now", set status `scheduled`, record the new date in `deferred until` and
the reason. The clock resets. Never push a deferred item before its date. Deferring must cost
the decider less than ignoring you, or they will ignore you.
- **Kill.** Set status `dropped` with a one-line reason. A dropped decision is closed, not failed.
- **Answered.** Set status `done`, record the answer, and act on it.
### 12. Verify before you push
Never push an item without checking that it is still open against its source of truth. An item
can sit open for weeks after the underlying reality changed, because nobody closed it. Pushing a
stale item is the fastest way to lose the decider's trust.
Before you raise any item, you must be able to complete this sentence:
> "I verified this is still open by reading [source] which showed [evidence]."
If you cannot complete it, search first. If the reality already changed, close the item instead
of pushing it.
| Item type | Source of truth | Check |
|---|---|---|
| Follow-up with a person (client, customer, candidate) | Their record in your customer database or notes | Read the current status field |
| Link, page or account issue | The live link or the settings page | Open it; confirm it is still broken |
| Install or setup task | The target machine or project | An existence check on the path, package or service |
| Travel, booking or appointment | The booking itself or the calendar | Confirm the date and status |
| Deploy, migration or release | The repository or release log | Look for the commit, tag or release entry |
| Metric (revenue, signups, stock) | The raw data file or the analytics tool | Read the raw rows, never a summary written by an earlier session |
| Any ledger item | The ledger plus recent session notes | Confirm no later note already closed it |
When you check a raw data file, confirm its layout and the date span it covers before you read
a number from it.
---
## Does NOT fire on
- Lookups and status checks the search can answer.
- Gaps that are not load-bearing: state the assumption and move on.
- Creative latitude the decider granted ("use your judgment", "any approach is fine"): do not ask, but open your
reply with the assumptions you made.
- Questions a specialist agent scopes for itself.
- A fact already established earlier in the session.
## Relationship to a clarify-first rule
A clarify-first rule is a gate before you start risky work. This skill fires whenever a
load-bearing fact is missing, including mid-work and after delivery, and adds the escalation loop
a pre-action gate lacks. An instruction like "just do it" suppresses clarifying questions, not
disclosure: you still state your assumptions.
Other files
CONTEXT.template.mdYour details: who decides, where the agent searches, where the decision ledger lives and when the summaries run.
# Ask and push: context
Copy this file to CONTEXT.md next to SKILL.md and fill in every blank. The agent asks you for any blank it needs. Never put passwords, access keys or card numbers here.
## Decider
(Who answers the questions: a role or first name, and how they prefer to be asked.)
Example: The studio owner. Prefers multiple choice, one line per option.
## Where to search before asking
(Every place a fact might already live. The agent works through all of them before asking.)
Example: notes/ folder, the issue tracker, the project README, the shared drive "Ops" folder, the analytics dashboard.
## Credential stores
(Where credentials are kept, so the agent looks there instead of asking. Name the store, never the value.)
Example: the 1Password vault "agent-keys" (service account) or a separate Bitwarden account; the project's .env file, listed in .gitignore.
## Decision ledger
(Where unanswered questions are filed: a tracker project, a label, or the path to DECISIONS.md.)
Example: DECISIONS.md in the repository root. Or: GitHub Issues in the repository "your-org/ops", label "decide".
## Stable key format
(How keys are built so the same question is never filed twice.)
Example: ask:<area>:<short-question-slug>, e.g. ask:billing:annual-plan-discount
## Areas
(The areas an item can belong to, used for spreading the daily block.)
Example: product, billing, marketing, hiring, personal
## Critical incident marker
(What makes an item a critical incident that bypasses the age ladder.)
Example: severity = critical and label = incident
## Daily surfaces
(When the morning and evening summaries run, and where they appear.)
Example: Morning at 08:00 in the daily standup note; evening at 18:00 in the end-of-day note.
## Cap per surface
(Maximum decision items per surface. Default 3.)
Example: 3
## Standing decisions
(Answers the decider has already given that sub-agents' questions can be settled against.)
Example: Always use the existing email provider; never discount below the listed floor price without asking.
## Source of truth per item type
(Override or extend the verification table in SKILL.md with your real sources.)
Example: Client follow-ups: the contact record in the customer database. Deploys: the release list in the repository.
DECISIONS.template.mdA plain Markdown decision ledger for readers without a task tracker.
# Decisions ledger
Copy this file to DECISIONS.md (or the path named in CONTEXT.md). One row per open question. Search the key and the question text before adding a row.
Status values: decide · scheduled (deferred, date in "deferred until") · done · dropped.
Age uses the older of "opened" and "origin date". Bands: 0-3 listed · 4-7 re-raised · 8-14 blocking-named · 15+ kill it or do it.
<!-- Example row, not a real item. Never push it. Copy its shape into the table below.
| key | question | opened | origin date | blocks | options (recommended marked *) | status | deferred until | last pushed |
|---|---|---|---|---|---|---|---|---|
| ask:shop:returns-window | Keep the returns window at the current length or extend it for the holiday season? | YYYY-MM-DD | | Holiday returns page copy | *keep · extend | decide | | YYYY-MM-DD morning |
-->
| key | question | opened | origin date | blocks | options (recommended marked *) | status | deferred until | last pushed |
|---|---|---|---|---|---|---|---|---|
## Closed
| key | answer or reason | closed | status |
|---|---|---|---|
What you need
An AI coding agent: Claude Code, Codex CLI or Cursor (opens in new tab)
The skill is a markdown instruction file. You need an agent that reads it and can open your files.
- Install one agent: Claude Code (https://code.claude.com/docs/en/overview (opens in new tab)), Codex CLI (https://developers.openai.com/codex/cli (opens in new tab)) or Cursor (https://cursor.com/docs (opens in new tab)).
- Open the agent in the folder that holds your notes and docs.
- Install the skill with the steps in the install section.
GitHub CLI with GitHub Issues (opens in new tab)
An optional decision ledger in a public tracker instead of DECISIONS.md. The markdown file is enough on its own.
- Install gh from cli.github.com and sign in from your own terminal with gh auth login.
- Create a decide label in the repository: gh label create decide.
- New question: gh issue create --label decide, with the key in the title. Open list: gh issue list --label decide.
- Write the repository name and the label in CONTEXT.md.
1Password CLI (opens in new tab)
One of the key stores the agent checks before asking you for a key. Pick one store; you do not need all three.
- Install the CLI with the official guide.
- Create a vault that holds only the keys this agent needs. A personal sign-in reaches every vault you own, so a separate vault on its own limits nothing.
- Create a service account with read access to that one vault only: https://developer.1password.com/docs/service-accounts/ (opens in new tab).
- Put the service account's token into the agent's shell environment yourself, under the variable name the 1Password docs give. Never sign that shell in with your personal account, and never paste the token into the chat.
- On the agent's machine, turn off the 1Password app's CLI integration, or never approve an access prompt the agent's terminal raises. Never print the service account token.
- The agent passes a key straight into the command with op run --env-file=agent.env -- <command>, where agent.env holds only op://vault/item/field references, never values. op run masks the values it resolves.
- Write only the vault name in CONTEXT.md.
Bitwarden CLI (opens in new tab)
A second option for access keys, if you use Bitwarden.
- Install the CLI with the official docs.
- Create a separate Bitwarden account that holds only the keys this agent needs. A CLI session decrypts the whole account vault, so a folder or collection on your own account limits nothing. Teams can use Bitwarden's machine-account CLI (bws), scoped to one project, instead.
- Sign the agent's shell in with that separate account only, never with yours. Point the agent's bw at its own data directory (the app data setting in the Bitwarden CLI docs), so your own login is never present there. Never print the session key.
- The agent puts the value straight into the command on one line: my_key="$(bw get password <item>)" <command>, and the command reads my_key from its environment. It never runs bw get on its own, which prints the value.
- This form has no masking: never run the command with -v, --verbose, debug or trace flags, never use set -x, and never echo the variable.
- Write only that account's name in CONTEXT.md. Never paste a key, token or password into the chat.
A .env file listed in .gitignore (opens in new tab)
The simplest option: project keys in a local .env file that Git never sends to the repository.
- Create a separate .env file that holds only this agent's keys, and type them in yourself, in an editor.
- Add a .env line to .gitignore before your first commit.
- Write only the file path in CONTEXT.md, never the values. The tool that needs the file loads it. The agent never prints its contents.
Install
- Copy the skill folder to .claude/skills/ask-and-push/ in your project, or to ~/.claude/skills/ask-and-push/ for every project (Claude Code).
- In Codex or Cursor, paste the contents of SKILL.md into AGENTS.md at the repository root.
- In any other agent, paste SKILL.md into the project instruction file or the system prompt.
- Rename CONTEXT.template.md to CONTEXT.md, keep it next to SKILL.md and fill in every field.
- If you do not use a task tracker, copy DECISIONS.template.md to DECISIONS.md and put its path in CONTEXT.md.
It's working if
- When the agent lacks a load-bearing fact, the question sits at the top of its reply with options to pick from.
- Alongside the question, the agent lists the places it searched.
- An unanswered question lands in the ledger as a new row with a key, a date and a blocks field.
- The morning "decisions waiting" block holds at most three items, and older items show their age.
- For each item, the agent can finish the sentence naming the source it read to confirm the item is still open.
- After you defer an item with a date, it stays out of the blocks until that date.
Requirements
- An agent that reads a Markdown instruction file (Claude Code, Codex, Cursor or similar).
- Agent access to your notes, tasks or repository, so it can search before asking.
- One place for the decision ledger: a task tracker or a DECISIONS.md file.
- A fixed time of day when you read the agent's summary.
Questions
Will the agent bury me in questions?
It should not. It asks only after searching its sources, and only about facts that change a decision. The block in each summary is capped at three items, and the rest wait in the ledger.
What if I do not want to answer yet?
Defer the question with a date. The agent records the new date and the reason, the clock restarts, and the item stays away until that day. You can also kill the question.
Why does the agent force a do-it-or-kill-it choice after 15 days?
A question that has waited two weeks usually blocks nothing, or blocks something important. Either answer closes it, and more reminders without a choice only spend your attention.
Do I need a task tracker?
No. The DECISIONS.md file from the template is enough. It has columns for key, question, dates, the blocked item, options, status and the date of the last follow-up.
Why check the source before a follow-up?
The matter may have been resolved without anyone closing the ledger row. A reminder about something already handled trains you to ignore the whole block.
Where it fits
This skill sits next to the clarify-before-acting template: that one guards the start of risky work, this one covers missing facts during and after the work and escalates unanswered questions. It connects to the orchestrator template through one rule: sub-agents ask the orchestrator, which gathers their questions and passes on only those it cannot settle itself. The decision block fits into any morning or evening summary.
All skillsSources
- Claude Code docs: Skills (accessed 2026-09-22)
- OpenAI Codex: AGENTS.md guide (accessed 2026-09-22)
- Cursor docs: Rules (accessed 2026-09-22)
Questions about setting these up go in the Discord.Join free