Open Spec For Reason In Action

Re in Act

Re in Act extends reason into the action loop, so local disturbances are handled before they turn into extra round trips, noisy context, and brittle control in traditional ReAct agents.

Set the goal and guardrails once. Let small decisions happen where the work happens.

Read More

Start Here

Start with the docs, read the spec, dig into the rationale, or join the project.

From ReAct to Re in Act

How the flow changes: less stop-and-think, more structured action.

01

Reason-able Action Space (RAS)

One Reason-able Action Space can coordinate multiple act() and reason() steps before returning a denoised result.

1
act() gathers local evidence

Run tests, read logs, or fetch a document without pushing raw output back to top-level reasoning.

act('bash', 'npm test -- --reporter json')
2
reason() compresses the local signal

Turn noisy evidence into one bounded decision using an explicit goal, observation, relevant context, and constraints.

reason([ 'Goal: identify the best retry step.', observation, 'Relevant context: CI run after latest change.', 'Constraints and rules: return retry_cmd + reason only.', ], { retry_cmd: '', reason: '' })
3
act() + reason() keep the space moving

Execute the next step, inspect the result again, and only return a denoised outcome once the local job is actually settled.

act('bash', retry_cmd) -> reason(...) -> act('deploy' | 'notify')
02

Paradigm Shift

ReAct returns to the outer loop at every step. Re in Act keeps the work moving inside one RAS.

Legacy
Modern
Thin Action LayerReason-able Action Space Strengthens Local Action
Round-Trip Tax (Reason-Act-Observe)One Orchestrated Action Phase
Raw Intermediate Data in Main ContextIntermediate Data Stays in Reason-able Action Space
Probabilistic Micro-Control FlowDeterministic Runtime Control Flow
03

Two Action Forms

The same idea can run as code or shell pipelines. In both forms, deterministic Turing-complete control is stronger than probabilistic LLM-stepped flow.

The Interfaces

Two simple interfaces: one for local judgment, one for external action.

01

reason(prompt, example_output)

Turns goal plus local reality into structured output that the Reason-able Action Space can use right away.

reason ( prompt, example_output )
{
1"prompt""Goal: decide continue vs retry. Observation: noisy build log. Constraints: ignore ANSI noise; return action + reason.",// goal + observation + context + constraints
2"example_output"{"action": "continue", "reason": ""},// schema hint
3"→ data"{"action": "retry", "reason": "registry timeout"},// structured result
4"→ error""validation failed after 3 retries"// on failure
}
02

act(name, args) — Optional

Calls tools or external systems with explicit arguments, returning structured output and errors.

act() is optional — the spec provides it as a standard convenience. You may use any user-defined action strategy instead.
MUSTnameTool identifier — MCP tool, custom function, bash command, etc.
MUSTargsComplete tool arguments. Stateless — include all needed context.
returns → "content": [{type, text}], "isError": bool

Reason-able Action Spaces

What the RAS looks like in practice: multiple act() and reason() steps cooperating inside one RAS.

Code Reason-able Action Space (Python / TS)

Deterministic orchestration in scripts: branches, loops, retries, and validation happen in code, while `reason()` supplies bounded judgments. That gives the runtime Turing-complete deterministic control instead of probabilistic LLM-stepped control.

Source
build_analyzer.py
1
test_run = await act('bash', 'npm test -- --reporter json')
2
 
3
focus = await reason(
4
['Goal: pick the retry step.',
5
observation, 'Relevant context: latest CI run.',
6
'Constraints: return retry_cmd + reason only.'],
7
{"retry_cmd": "", "reason": ""},
8
)
9
 
10
retry_run = await act('bash', focus['data']['retry_cmd'])
11
decision = await reason(
12
['Goal: continue or escalate?',
13
retry_run['content'][0]['text'], focus['data']['reason'],
14
'Constraints: return action + reason only.'],
15
{"action": "continue", "reason": ""},
16
)
17
if decision['data']['action'] == 'escalate':
18
await act('notify', {'message': decision['data']['reason']})
19
print(decision['data']['reason'])
20
else:
21
await act('deploy', {'target': 'production'})
22
print('deployed')
Action Flow
flowchart

Bash Reason-able Action Space

Unix-style pipelines compose `reason` and `act` in a single action phase. Shell gives you deterministic, Turing-complete control flow, while the LLM stays confined to bounded local judgments.

$ act --manual | \
reason \
--prompt "Goal: find the tools needed to collect the most relevant API and documentation context for this task." \
--prompt - \
--prompt "Constraints: return only a JSON array of tool names. Prefer the smallest sufficient set." \
--structure '["tool_name"]' | \
jq -r '.data[]' | while read -r name; do act --manual "$name"; done
pipe |JSONpipe |acttool catalogreasonselect toolsjqunwrap namesactexpand defs
Data flowStructured JSONShell action

Reason-able Action Space as Harness

When the optional agent() extension is used, the Reason-able Action Space is the harness.

Agent Harness Model

This is specifically the agent extension pattern: agent() runs delegated work inside the Reason-able Action Space, returns text and trajectory, reason() verifies those signals inside the RAS, and deterministic limits are enforced inside the RAS.

01Agent Extension

Delegated agent work

When the optional agent() extension is present, the RAS can host delegated agent work inside one RAS instead of turning that delegation into a separate top-level architecture.

02Local Check

Post-agent verification

In this pattern, reason() is not acting as an agent. It checks both text and trajectory returned by agent(), extracts the signal that matters, and turns it into structured control data.

03Runtime Control

Deterministic boundaries

Loops, max iterations, timeout, escalation, and stop conditions live in the runtime. That is what makes the Reason-able Action Space the harness for agent() rather than just another prompt wrapper.

This harness framing belongs to the optional agent() extension. The point is not that reason() is agent-related by itself, but that once agent()is introduced, the RAS becomes the harness that contains delegated work, verification, and escalation. For the broader harness term, see Harness engineering. See Agent Interface Extension.