approval

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package approval closes the loop that makes a headless worker stall.

A coding agent run with -p executes what it is allowed to and asks about the rest. Headless, there is nobody at the terminal to answer, so the run either hangs until something kills it or the operator pre-approves everything up front — trading the ability to say no for the ability to finish. Both are bad answers to a question that has a good one: there IS a person present, one conversation upstream, and MCP has a way to reach them.

Claude Code's --permission-prompt-tool names an MCP tool it will call instead of prompting. This package is that tool. It serves a tiny MCP endpoint on loopback, hands the worker a generated config pointing at it, and turns each permission request into an elicitation on the session that delegated the task — so the user approves it where they already are.

Two properties are deliberate. Each run gets a single-use URL with an unguessable token, revoked the moment the turn ends, because anything that can reach this endpoint can approve commands on this machine. And when the orchestrating client cannot elicit, requests are denied rather than allowed: a worker told "no" reports that it was blocked, which is recoverable, while a worker silently granted everything is not.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Broker

type Broker struct {
	// contains filtered or unexported fields
}

Broker serves the approval endpoint and tracks the grants that may use it.

func Start

func Start(configDir string, decide Decider) (*Broker, error)

Start brings up the approval endpoint on loopback and returns a broker.

It binds to an ephemeral port on 127.0.0.1 specifically: the endpoint grants the power to run commands on this machine, so it must not be reachable from anywhere the machine itself is not.

func (*Broker) Addr

func (b *Broker) Addr() string

Addr reports where the endpoint is listening, for logging.

func (*Broker) Close

func (b *Broker) Close()

Close shuts the endpoint down.

func (*Broker) NewGrant

func (b *Broker) NewGrant(taskID string) (*Grant, error)

NewGrant issues a single-use approval URL for one task and writes the config file the agent will be launched with.

type Decider

type Decider func(ctx context.Context, req Request) Decision

Decider answers a permission request. It is called off the broker's lock and may block for as long as its context allows.

type Decision

type Decision struct {
	Allow   bool
	Message string // why, when denied — the worker sees this and can adapt
}

Decision is the answer to one permission request.

type Grant

type Grant struct {
	ConfigPath string
	ServerName string
	ToolName   string
	// contains filtered or unexported fields
}

Grant is one run's permission to ask. It carries the path of the MCP config file the agent must be pointed at, and is void once closed.

func (*Grant) Close

func (g *Grant) Close()

Close revokes the grant and removes its config file. After this the URL answers every request with a denial.

func (*Grant) PermissionTool

func (g *Grant) PermissionTool() string

PermissionTool is the value for --permission-prompt-tool that matches the config this package writes.

type Request

type Request struct {
	TaskID    string
	ToolName  string
	Input     map[string]any
	ToolUseID string // the agent's own id for this call, for correlating logs
}

Request is one tool call the worker wants to make.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL