-
Notifications
You must be signed in to change notification settings - Fork 5
EN Course 01 Minimal Agent Loop
The smallest useful agent loop has four steps:
- accept user input
- append it to conversation state
- call the model with the accumulated messages
- stream the assistant response back
In bash-agent this grows into agent_loop, but the core shape stays simple.
store_conv_add_user "$user_input"
messages="$(store_conv_get_messages)"
llm_call "$messages"The real loop adds retries, tool calls, compaction, stats, display events, and stop handling. Those are layers around the same center: a user turn becomes a request, and the response is either final text or a request to run tools.
The command-line entrypoint only decides configuration and input source. It does not own agent behavior.
main() {
parse_args "$@"
util_find_awk_dir
validate_config
store_session_init
util_load_tool_defs
if [[ "$INTERACTIVE" == true ]]; then
interactive_mode
elif [[ -n "$USER_INPUT" || ! -t 0 ]]; then
local input="$USER_INPUT"
[[ -z "$input" ]] && input=$(cat)
( exec 5> "$INPUT_FIFO"; util_write_msg "USER_INPUT" "0" "$input" >&5 ) &
agent_main_loop
else
INTERACTIVE=true
interactive_mode
fi
}--print is parsed as stream-json:
--print) OUTPUT_FORMAT="stream-json"; shift ;;That keeps one execution path. Interactive input, prompt arguments, stdin input, and --print all enter the runtime through the same message queue and agent loop.
The user message is written before the model call:
store_conv_add_user() {
local content; content=$(util_json_escape "$1")
printf '{"role":"user","content":"%s"}\n' "$content" >> "$CONV_FILE"
}That makes the conversation file the durable state of the session. If a later model call fails, the user turn is still present and the session can continue from the same state.
The loop boundary is not the terminal prompt. It is the semantic turn:
user input -> model request -> optional tools -> assistant result
Interactive mode, --print, and sub-agent continuation all drive the same loop. This keeps the runtime behavior aligned even when the input source changes.
Streaming Transport explains how the model response is streamed and normalized before the loop consumes it.