Skip to content

Ask a human #505

Description

@smebberson

Hey Matt - Sandcastle is fantastic - love what you've done here. I watched your video and wondered why you didn't power this with an XState machine 😆

In my experience, my comfort and success level with agentic development skyrocketed when I started suffixing this to all of my prompts:

Let me know if you have any questions.

It really helped me steer the AI when my instructions weren't enough. It stops the AI from guessing what you want. Sandcastle agents currently have no way to ask for clarification - when blocked, the agent comments on the issue and moves on (or stops). Adding "Let me know if you have any questions" to prompts works well interactively but has no mechanism in the AFK orchestration loop.

Proposal

Add a question signal — a structured XML block the agent emits when it needs clarification. The orchestrator pauses the iteration loop, routes the question to the human, and resumes with the answer injected into the next iteration's prompt.
Agent output:

<questions issueNumber="42">
    <title>Database driver choice</title>
    <prose>Need to decide before implementing the connection pool.</prose>
    <question>
        <title>Which driver?</title>
        <prose>The codebase has no existing database dependency.</prose>
        <options>
            <option><title>pg</title><prose>PostgreSQL client</prose></option>
            <option><title>mysql2</title><prose>MySQL client</prose></option>
        </options>
    </question>
</questions>

Answer channels:

  • Terminal (stdout mode) — Clack prompts render inline, user types answers immediately
  • GitHub Issues (file/stdout mode) — Agent posts questions as a comment, applies needs-info label, host-side polling loop watches for new comments, backs off over time (5min → 15min → 30min → 1hr)
  • Custom callback — async ({ questions }) => answers for Slack, Discord, etc.

Key behaviours:

  • Question iterations do not count against maxIterations
  • Sandbox is torn down during the wait; session capture + --resume handles continuity
  • Configurable timeout (default 24h) with QuestionTimeoutError
  • First response wins when multiple handlers are configured

Implementation touchpoints:

  • Orchestrator.ts — question signal detection (parallel to completion signal), pause/resume loop, answer injection
  • QuestionSignal.ts — XML parsing, types
  • QuestionHandler.ts — handler interface + built-in terminalQuestions() and githubIssueQuestions()
  • Display.ts — new question method (Clack prompts / log entries)
  • run.ts — new RunOptions: questionHandling, questionTimeoutMs, questionPollIntervalMs
  • Prompt templates — add instructions
  • errors.ts — QuestionTimeoutError

Why this approach

Mirrors the existing completion signal pattern. Uses GitHub issues as the natural communication medium (agent already has gh CLI, needs-info label already exists in triage). Opt-in — no questionHandling option means current behavior is unchanged.

What do you think?

Is something like this interesting to you? Something you think you'd use? Something you think Sandcastle would benefit from?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions