Skip to content
Agentmart
Submit a tool

pending-questions

Ask the owner a decision you need, list what is waiting on him, close a question once he has answered, or run the reminder.

Skill by sonichi

IndexedMIT★ 400
Write a review

Chalk Labs

Need help deploying pending-questions?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/sonichi-pending-questions

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Ask the owner a decision you need, list what is waiting on him, close a question once he has answered, or run the reminder. Use when blocked on the owner's word, or asked "what are you waiting on me for?".

Use cases: documents

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Python package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/pending-questions

What's inside

Skill name
pending-questions
Description
Ask the owner a decision you need, list what is waiting on him, close a question once he has answered, or run the reminder. Use when blocked on the owner's word, or asked "what are you waiting on me for?".
License
MIT
Instructions
152 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Agent Skills spec issues

  • files: referenced but missing: scripts/ask-owner.py, scripts/pending_questions_compat.ingest_legacy_file_entries

Files (12)

  • SKILL.md
  • compact-carry.py · hooks/
  • manifest.json
  • pending_questions_ask.py · scripts/
  • pending_questions_compat.py · scripts/
  • pending_questions_ledger.py · scripts/
  • pending_questions_md.py · scripts/
  • pending_questions_outbox.py · scripts/
  • pending_questions_remind.py · scripts/
  • pending_questions_room_db.py · scripts/
  • pending_questions_store.py · scripts/
  • pq.py · scripts/

SKILL.md (first lines)

# pending-questions

One CLI over the owner's pending questions, and the one store behind them: the
"Pending questions" database in the owner's room. Each question is a row carrying its
Host; a host reads and writes only its own rows, and the owner sets a row's Status
himself (code never writes it — its own marks live in the Recovery and Closed cells).

The room is `PENDING_QUESTIONS_ROOM`: env, then this manifest's `config`, then the host's
`<workspace>/state/pending-questions-room`; unset, the owner's DM. Point every host of the
owner at one room shared by him and all his Sutandos. The collab service is the room
capability's own, unless `PENDING_QUESTIONS_COLLAB_URL` names one (env, then this manifest's
`config`, per `skills/MANIFEST.md`); the adapter's `room_store(..., collab_url=)` is the CLI
tier above both.

```bash
python3 skills/pending-questions/scripts/pq.py ask "<question>" [--context "<why / options>"] \
    [--task-file <workspace>/tasks/<task>.txt] [--urgency live|durable] \
    [--default-action "<what Approve does>" --reason "<why>"] [--option "Hold=wait"] \
    [--priority High|Medium|Low]
python3 skills/pending-questions/scripts/pq.py list [--json]
python3 skills/pending-questions/scripts/pq.py reconcile
python3 skills/pending-questions/scripts/pq.py resolve <ask-id> [--answered]
python3 skills/pending-questions/scripts/pq.py remind [--force]
python3 skills/pending-questions/scripts/pq.py clicks [--json]
python3 skills/pending-questions/scripts/pq.py ack <ask-id> --token <token>
```

**Trigger: any time you would write a question for the owner into terminal or summary text, file
it instead** with `ask` (or `scripts/ask-owner.py`; add `--unless-open` to file nothing when an
open row already has that question — it reports `already open: [<id>]`). The terminal and a compaction summary reach no one.
This skill's `hooks/compact-carry.py` keeps owner questions out of compaction summaries and, after
one, has the core file any never-asked question it carried; `session-state.md` shows only the
count (`python3 src/pending_questions_reader.py summary`).

- `ask` queues the question to the owner (the task's conversation only for an
  owner-tier task in his DM; otherwise his DM), saves it to the outbox, writes the row born
  with its `**Sent:**` record, and once that exact row is confirmed complete commits the
  store-history marker and THEN deletes the outbox file — a marker that cannot be written
  keeps the file (`history: FAILED` in the report) so the local evidence outlives the
  failure. Only after that confirmation does it reconcile the older backlog. Room subprocess
  calls share one operation budget (90 seconds by default), so failures cannot renew the
  timeout for each older question; the held entries remain for a later explicit reconcile.
  The shared reconcile pass applies that budget to every caller, including `pq reconcile`
  and reminders. Resolving an answer shares it across reconciliation and the row close.
  If the outbox cannot hold the question, NO row is written: the owner is still
  asked, and the report says nothing holds it. Read the output: a `FAILED` line is not an
  ask. Then continue; never block.
- `list` is READ-ONLY — it writes no file, not even the history marker — and lists each ask
  id in exactly one bucket, by precedence: a terminal or locally closed row is done; a
  complete open row waits; an open row whose body has not landed is stood in for by its held
  entry; a held entry with no row waits, marked `(not yet in the room)`, or is done when
  closed locally; a local close naming neither is `closed locally; its row is not in view
  yet` (neither open nor done, `pending_close` in `count`). When the room cannot be read it
  prints `pending questions: UNKNOWN — room unreachable (…)` and only what is held locally;
  it never prints a zero it did not measure. Once a row of this workspace was ever confirmed
  (written, replayed, ingested or observed by a reconcile), a room that cannot be reached is
  an outage, not an empty outbox — whatever became of the one-time introduction message.
- `reconcile` is the explicit pass: outbox replay, local close records, stale marks, the
  transitional legacy ingest, and the history backfill for rows that predate the marker.
  Legacy ingest refuses an archive boundary hidden by damaged Markdown before creating
  rows or marking source entries moved; it reports the affected line numbers.
  Every step commits the history marker before it releases local evidence (an outbox entry,
  a close record, a legacy file entry), and keeps that evidence when the commit fails. `ask`
  and `remind` run it; `list` does not.
- `resolve` closes a row as Resolved (or Answered with `--answered`). It never reopens a
  closed row. When the room cannot be written, the closure is recorded locally
  (`<outbox>/closed/<ask_id>.json`) and applied by the next `reconcile` — but only for a
  question the outbox holds, or in outage mode (a row was confirmed here before); an unknown
  id with neither is refused and changes no count. The replay retires a local close only
  once its row is closed (or seen closed) AND complete — its body landed; a row the store
  view does not show is ambiguous and an incomplete one is still being filed, so in both
  cases the record stays and `reconcile` reports it.
- `remind` is the only way a reminder is sent (`src/check-pending-questions.py --notify`
  with this skill's adapter). Nothing is scheduled, and no pass surfaces questions: the
  owner is asked once, as questions come up, and reminded when he asks. The one exception
  completes that single ask: every pass, flagless included, sends the pointer for a decision
  card the gateway never posted (see The reminder, below).

## Decision cards (the ask)

A question asked with `--default-action` and/or `--option` whose destination is s.space (its
task's bridge, else the bridge the owner was last active on) is asked as a decision card, built by
`src/hitl/cards.py` (the one builder every card producer uses): one button per choice — with a
default, one per `ordered_options()` entry, Approve first and carrying it; with options alone,
exactly the options as given, with no Approve — and `subject.choices` holding each consequence.

- **Order.** The card is built and its id allocated; the question is held in the outbox and its
  row is written, both naming that id (`**Sent:** card hitl_<id> for ag2space owner-dm (decision
  card) at <time>`); only then is the card stored, for the s.space gateway to post in the
  owner's DM: the asking task's own conversation when that is his s.space DM (`req.room`, so
  his click reaches the session bound to that room), else the gateway's default owner DM. No
  card exists without a durable question. The ask reports
  `stored, not yet shown: decision card hitl_<id>`: storing is not showing.
- **One surface.** Once a card exists, no text is sent for that question. `create_card` returns
  stored, not stored or unknown: a store that raised but whose card file is there, or one that
  cannot be checked, is kept as the card, and the report says no text was sent.
- **Text instead.** Only when the card cannot be built, the question cannot be held (then no card
  is stored), or the card is provably not stored; and for every other bridge. On a definite card
  failure the text goes to the question's own destination with the row's own link (the one the
  row write returned), and the question is held again, flagged `redeliver`, naming that file. For
  a landed row, in order: the store history is committed, the row is rewritten (one body write,
  `RoomDbStore.redeliver`), and only then does the held entry go — a history that cannot be
  written keeps the hold, so an outage never counts the question as zero;
  a row that could not be rewritten, or whose write was never confirmed, takes the record at the
  next reconcile, which replays the entry and rewrites the row before releasing it. A death
  before the hold leaves a record naming an absent card, which the next `--notify` reminder
  reads as due and texts.
- **The reminder.** It never sends text for a question whose card is live (pending or clicked) or
  whose store cannot say — `--force` included; such questions are left to the card. Once posted,
  the question's last-asked time is the gateway's `notified_at`. A live card with no post
  recorded 30 minutes (`CARD_POINTER_GRACE_SEC`) after it was stored gets a text pointer. Under the
  HITL store lock the card is re-checked (live, unposted, no pointer sent, no live claim) and a
  claim (a token with its own lease, `pointer_lease`) is stamped; only the claimant publishes,
  then marks it sent (`pointer_sent_at`). The claim's lease is the same elapsed-time lease as a
  click's (see Decision-card clicks): each reminder pass credits at most `POINTER_MAX_STEP_SEC`
  (150 s) and nothing for a backward step, and a claim whose lease has run 5 minutes
  (`POINTER_CLAIM_RETRY_SEC`) with no sent mark — its claimant died or failed to publish — is
  claimed again, with a new lease, and retried. So the pointer is at-least-once: overlapping
  reminders queue one per claim, a death before the publish is retried later, a death between

From sonichi/sutando, MIT.

More from sonichi/sutando

Signals

Stars
400
Forks
98
Open issues
1,202
Last commit (this folder)
Oct 19, 2026 (12 days ago)
Last release
Aug 20, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
Website
sutando.ai
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from sonichi

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get pending-questions running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying pending-questions?

CallGet help
Cite this page

pending-questions skill. Agent Mart. https://agentmart.dev/skills/sonichi-pending-questions (last updated 2026-10-24)