### Install Runtime Tools (Debian/Ubuntu) Source: https://github.com/frntn/plankclaw/blob/main/README.md Installs essential runtime tools for the agent on Debian-based systems. ```sh sudo apt install curl jq # Debian/Ubuntu ``` -------------------------------- ### Configuration File Example Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Example environment configuration file for Planckclaw. Sets essential API keys, channel IDs, and directory paths. Includes settings for history management. ```shell export DISCORD_BOT_TOKEN="MTI3..." export DISCORD_CHANNEL_ID="1234567890123456789" export ANTHROPIC_API_KEY="sk-ant-..." export PLANCKCLAW_DIR="./memory" export HISTORY_MAX="200" export HISTORY_KEEP="40" ``` -------------------------------- ### websocat Installation Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Provides instructions for installing the 'websocat' utility, a runtime dependency for the Bridge Interact component, via cargo or by downloading a static binary. ```text cargo install websocat or download static binary (~3 MB) from GitHub releases. ``` -------------------------------- ### Install Build Tools (Fedora) Source: https://github.com/frntn/plankclaw/blob/main/README.md Installs necessary build tools for compiling the agent on Fedora systems. ```sh sudo dnf install nasm binutils make # Fedora ``` -------------------------------- ### Minimal Claw Example Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md A minimal example of a Plankclaw claw implementation. ```shell # claws/time.sh (7 lines): minimal claw example ``` -------------------------------- ### Install Build Tools (Debian/Ubuntu) Source: https://github.com/frntn/plankclaw/blob/main/README.md Installs necessary build tools for compiling the agent on Debian-based systems. ```sh sudo apt install nasm binutils make # Debian/Ubuntu ``` -------------------------------- ### System Claw Example with /proc Access Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md A Plankclaw claw implementation that includes access to the /proc filesystem. ```shell # claws/system.sh (14 lines): claw with /proc access ``` -------------------------------- ### Add New Tool Claw Script Example Source: https://github.com/frntn/plankclaw/blob/main/README.md Example of a shell script to add a new tool to PlanckClaw. The script defines the tool's name, description, and input schema, and handles tool execution via a case statement. ```sh #!/bin/sh #TOOLS:{"name":"my_tool","description":"What it does","input_schema":{"type":"object","properties":{}}} case "$1" in my_tool) printf 'result here' ;; esac ``` -------------------------------- ### JSON Navigation Algorithm Example Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Illustrates the step-by-step process for navigating a JSON structure to extract a specific string value, such as content[0].text. ```text 1. Enter root object (depth 0) 2. Scan keys at depth 0 until key == "content" 3. Enter array (depth 1) 4. Enter first element at index 0 (depth 2, it's an object) 5. Scan keys at depth 2 until key == "text" 6. Extract the string value (handling \" and \\ escapes) 7. Return extracted string ``` -------------------------------- ### Example Summary Memory Content Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Shows the free-form UTF-8 text content for the summary.md file, generated by an LLM during compaction. ```text The user's name is Marc. He works in tech. He is interested in minimalist AI agents and x86-64 assembly. He prefers responses in French, concise. Current project: building the smallest possible AI agent (planckclaw). ``` -------------------------------- ### Example Soul Memory Content Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Illustrates the free-form UTF-8 text content for the soul.md file, defining the assistant's persona and behavior. ```text You are Planck, a minimalist personal assistant. You respond in French by default. You are concise and direct. You remember previous conversations through your summary. ``` -------------------------------- ### Run PlanckClaw with Discord Bridge Source: https://github.com/frntn/plankclaw/blob/main/README.md Launches the PlanckClaw agent using the Discord bridge for communication. Requires 'jq' and 'websocat' to be installed. ```shell ./planckclaw.sh bridge_discord.sh # discuss via Discord (not CLI) ``` -------------------------------- ### Example History JSONL Content Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Demonstrates the structure of the history.jsonl file, containing conversation history as JSON objects, one per line, in user/assistant pairs. ```json {"role":"user","content":"Hello"} {"role":"assistant","content":"Hi! How are you?"} {"role":"user","content":"Can you explain Unix FIFOs?"} {"role":"assistant","content":"FIFOs (named pipes) are..."} ``` -------------------------------- ### Testing bridge_claw.sh Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Demonstrates how to test tool discovery and execution by sending a '__list_tools__' command to the claw input and reading the response from the claw output. ```bash echo '__list_tools__' > /tmp/planckclaw/claw_in and read from claw_out ``` -------------------------------- ### Agent Main Loop: Tool Execution Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Format for executing a specific tool, including its name and input parameters. ```text {name}\t{input}\n ``` -------------------------------- ### Planckclaw Launcher Script Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Initializes the Planckclaw environment by setting up directories, FIFOs, and default memory files. It then launches the bridge scripts and the main planckclaw process in the background. Requires a umask to be set. ```shell #!/bin/sh . ./config.env umask 077 mkdir -p /tmp/planckclaw memory mkfifo /tmp/planckclaw/interact_in mkfifo /tmp/planckclaw/interact_out mkfifo /tmp/planckclaw/brain_in mkfifo /tmp/planckclaw/brain_out mkfifo /tmp/planckclaw/claw_in mkfifo /tmp/planckclaw/claw_out [ -f memory/soul.md ] || echo "You are a helpful personal assistant." > memory/soul.md [ -f memory/history.jsonl ] || touch memory/history.jsonl [ -f memory/summary.md ] || touch memory/summary.md ./bridge_brain.sh & ./bridge_claw.sh & ./planckclaw & ./bridge_discord.sh & wait ``` -------------------------------- ### Agent Main Loop: List Tools Command Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md The command written to claw_in to request a list of available tools from the agent. ```text __list_tools__\n ``` -------------------------------- ### Build PlanckClaw Binary Source: https://github.com/frntn/plankclaw/blob/main/README.md Builds the PlanckClaw agent binary using make. This process compiles the assembly code into a small, static executable. ```shell git clone https://github.com/frntn/plankclaw.git && cd plankclaw ./configure # check prerequisites make # build the ~7KB binary cp config.env.example config.env # add your Anthropic API key ./planckclaw.sh # run in terminal mode by default ``` -------------------------------- ### Asm JSON Builder Template + Fill Approach Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Suggests a method for building JSON in assembly by pre-storing a skeleton in .data, copying it to a buffer, and then filling in variable content at marker positions. ```assembly ; Use section .data for constant strings (system prompt default, ; JSON templates, FIFO paths) ; ... ; The JSON builder can use a "template + fill" approach: ; pre-store JSON skeleton in .data with placeholder markers, ; copy to buffer, then memcpy variable content at marker positions ``` -------------------------------- ### Tool Discovery Request Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md The agent sends '__list_tools__\n' to discover available tools before each message. This enables hot-reloading of tools. ```text __list_tools__ ``` -------------------------------- ### Manual Claw Protocol Test: Discovery Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Test the tool discovery mechanism by sending '__list_tools__\n' to claw_in and observing the output on claw_out. ```sh # Test discovery printf '__list_tools__\n' > /tmp/planckclaw/claw_in cat /tmp/planckclaw/claw_out ``` -------------------------------- ### Makefile for Planckclaw Agent Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md The Makefile defines variables and targets for assembling and linking the x86-64 NASM assembly source into the planckclaw binary. ```makefile ASM = nasm LDFLAGS = -s -n TARGET = planckclaw all: $(TARGET) $(TARGET): planckclaw.o ld $(LDFLAGS) -o $@ $^ planckclaw.o: planckclaw.asm $(ASM) -f elf64 -o $@ $^ size: $(TARGET) wc -c $(TARGET) size $(TARGET) clean: rm -f planckclaw.o $(TARGET) .PHONY: all size clean ``` -------------------------------- ### Manual Claw Protocol Test: Execution Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Test tool execution by sending a tool name and input JSON to claw_in and observing the result on claw_out. ```sh # Test execution printf 'get_time\t{}'\n' > /tmp/planckclaw/claw_in cat /tmp/planckclaw/claw_out ``` -------------------------------- ### FIFO Format: claw_in/claw_out (Discovery) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Format for discovery requests and responses between Agent and Tools Bridge. Discovery requests are a simple string, while responses are a JSON array of tool definitions. ```text Discovery request: __list_tools__\n ``` ```text Discovery response: [{tool JSON array}]\n\n ``` -------------------------------- ### Tool Discovery Response Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md The bridge responds with a JSON array of tool definitions, including name, description, and input schema. This response is terminated by \n\n. ```json [{"name":"get_time","description":"Get current UTC time as Unix timestamp","input_schema":{"type":"object","properties":{}}},{"name":"system_status","description":"Get system uptime, memory, load, and process count","input_schema":{"type":"object","properties":{}}}] ``` -------------------------------- ### Tool Execution Request Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md The agent sends a tool execution request formatted as '{name}\t{input_json}\n'. The input_json is a JSON object with parameters for the specified tool. ```text {name} {input_json} ``` -------------------------------- ### FIFO Format: claw_in/claw_out (Tool Call) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Format for tool call requests and responses between Agent and Tools Bridge. Requests include the tool name and input JSON, while responses are plain text results. ```text Tool call request: {name}\t{input_json}\n ``` ```text Tool call response: {result_text}\n\n ``` -------------------------------- ### Bridge Claw Script Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Scans claws/*.sh using shell builtins for discovery with zero forks. ```shell # bridge_claw.sh (~51 lines): scans claws/*.sh with shell builtins (zero fork for discovery) ``` -------------------------------- ### Agent to Bridge LLM Prompt (Compaction) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Used for sending a prompt to the LLM for memory compaction. The 'system' field provides instructions for summarization. The 'messages' field includes existing summary and conversation history. ```json {"model":"claude-haiku-4-5-20241022","max_tokens":2048,"system":"You are a memory compaction assistant. Summarize the following conversation, preserving: key facts about the user, their preferences, decisions made, ongoing projects, and important context. Be concise but complete. Output only the summary, no preamble.","messages":[{"role":"user","content":"EXISTING SUMMARY:\n[summary.md]\n\nCONVERSATION TO SUMMARIZE:\n[lines 0..N-HISTORY_KEEP from history.jsonl]"}]} ``` -------------------------------- ### Agent Main Loop: Response to Interact Out Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md The format for sending a processed response back to the user via the interact_out FIFO. ```text {channel_id}\t{response}\n ``` -------------------------------- ### Tool Execution Bridge Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Manages the execution of tools based on input from a FIFO. It can list available tools or execute a specified tool with given input, writing the result to another FIFO. No specific environment variables are required. ```shell #!/bin/sh while IFS= read -r line; do if [ "$line" = "__list_tools__" ]; then # List available tools echo "[\n {\"name\":\"get_time\",\"description\":\"Get current Unix timestamp\"},\n {\"name\":\"system_status\",\"description\":\"Get system uptime, memory, and load average\"}\n]\n\n" > /tmp/planckclaw/claw_out elif [[ "$line" =~ ^([^[:tab:]]+)\t(.*)$ ]]; then # Execute tool TOOL_NAME="${BASH_REMATCH[1]}" TOOL_INPUT="${BASH_REMATCH[2]}" RESULT="" case "$TOOL_NAME" in get_time) RESULT=$(date +%s) ;; system_status) UPTIME=$(cat /proc/uptime | awk '{print $1}') MEMINFO=$(cat /proc/meminfo) LOADAVG=$(cat /proc/loadavg) RESULT="Uptime: $UPTIME seconds\nMemory:\n$MEMINFO\nLoad Average: $LOADAVG" ;; *) RESULT="Error: Unknown tool '$TOOL_NAME'" ;; esac echo "$RESULT\n\n" > /tmp/planckclaw/claw_out fi done < /tmp/planckclaw/claw_in ``` -------------------------------- ### Claw Script Tool Definition Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md A claw script declares its tools using a '#TOOLS:' comment followed by Claude-compatible JSON. It must be executable and implement tools in a 'case' statement. ```sh #!/bin/sh #TOOLS:{"name":"weather","description":"Get weather for a city","input_schema":{"type":"object","properties":{"city":{"type":"string","description":"City name"}},"required":["city"]}} case "$1" in weather) city=$(printf '%s' "$2" | jq -r '.city') curl -s "https://wttr.in/${city}?format=3" ;; esac ``` -------------------------------- ### Tool Execution Response Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md The bridge returns the tool's result as plain text, terminated by \n\n. If the tool is unknown, it returns 'Unknown tool: {name}\n\n'. ```text {result_text} ``` -------------------------------- ### Manual Claw Script Test Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Test a claw script directly by executing it with the tool name and input JSON as arguments. This bypasses the FIFOs and is useful for debugging. ```sh # Test a claw script directly (no FIFOs needed) ./claws/time.sh get_time '{}' ``` -------------------------------- ### LLM Error Handling: Timeout Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Illustrates the error response written to fifo_llm_res when the LLM bridge encounters a timeout or a 5xx server error. ```json {\"error\":\"timeout\"}\n\n ``` -------------------------------- ### Agent to Bridge LLM Prompt (Normal) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Used for sending a normal prompt to the LLM. The 'system' field is constructed from soul.md and summary.md. The 'messages' field contains recent history and the current message. ```json {"model":"claude-haiku-4-5-20241022","max_tokens":1024,"system":"[SOUL.MD CONTENTS]\n---\nCONVERSATION SUMMARY:\n[SUMMARY.MD CONTENTS]","messages":[{"role":"user","content":"msg1"},{"role":"assistant","content":"rep1"},{"role":"user","content":"current_msg"}]} ``` -------------------------------- ### PlanckClaw Architecture Diagram Source: https://github.com/frntn/plankclaw/blob/main/README.md Visual representation of the PlanckClaw agent's components and their interactions, including Discord connector, bridge interact, agent, bridge tool, bridge brain, and Anthropic API connector. ```text ┌───────────────────┐ │ Discord │ ┌┤ Connector │ ┌┤└──────────────────┬┘ │└──────────────────┬┘ └────┬──────────▲───┘ │ │ ┌───▼──────────┴───┐ │ BRIDGE INTERACT │ │ (shell script) │ └───┬──────────▲───┘ │ │ │ │ ┌───▼──────────┴───┐ ┌───────────────────┐ │ │ ┌──────────────────┐ ┌│ time.sh │ │ AGENT ├──────► BRIDGE TOOL ├─────► ┌┤└───────────────────┘ │ 6.8KB x86-64 ◄──────┤ (shell script) ◄───── ┌┤└──────────────────┬┘ │ │ └──────────────────┘ │└──────────────────┬┘ └───┬──────────▲───┘ └───────────────────┘ │ │ │ │ ┌───▼──────────┴───┐ │ BRIDGE BRAIN │ │ (shell script) │ └───┬──────────▲───┘ │ │ │ │ ┌───▼──────────┴────┐ │ Anthropic API │ ┌┤ Connector │ ┌┤└──────────────────┬┘ │└──────────────────┬┘ └───────────────────┘ ``` -------------------------------- ### Manual Interact Protocol Test Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Provides shell commands to manually test the Interact Protocol by simulating the agent and a bridge in separate terminals. ```sh # Terminal 1: simulate the agent (echo back what it receives) while IFS= read -r line; do echo "agent received: $line" >&2 printf '%s ' "$line" > /tmp/planckclaw/interact_out done < /tmp/planckclaw/interact_in # Terminal 2: simulate a bridge sending a message printf 'test-channel Hello world ' > /tmp/planckclaw/interact_in # Terminal 3: simulate a bridge reading the response cat /tmp/planckclaw/interact_out ``` -------------------------------- ### Testing bridge_brain.sh Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Provides commands to test API connectivity by sending a JSON payload to the brain input and reading the response from the brain output. ```bash echo '{"model":"claude-haiku-4-5-20251001","max_tokens":64,"messages":[{"role":"user","content":"Say hello"}]}' > /tmp/planckclaw/brain_in and read from brain_out ``` -------------------------------- ### Agent <-> LLM FIFO Format Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Specifies the format for requests and responses between the Agent and the LLM using compact JSON on a single line, delimited by double newlines. ```json {compact JSON on a single line}\n\n ``` -------------------------------- ### Bridge LLM to Agent Response (Success) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md A successful response from the LLM via the bridge. The agent should navigate the 'content' key, then the array, then the object, to extract the 'text' value. ```json {"id":"msg_01X","type":"message","role":"assistant","content":[{"type":"text","text":"The actual LLM response here"}],"model":"claude-haiku-4-5-20241022","stop_reason":"end_turn"} ``` -------------------------------- ### ld Flags Explanation Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Explains the purpose of specific linker flags used in the Makefile: '-s' for stripping symbols and '-n' for disabling page alignment to achieve a more compact binary. ```text -s : strip symbols (saves ~1-2 KB) -n : no page alignment (allows more compact ELF binary) ``` -------------------------------- ### Manual Bridge Test: Bridge Response Simulation Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Simulate a brain bridge responding to a payload received from the agent. The response is written to the bridge's output FIFO as compact JSON terminated by \n\n. ```sh # Terminal 2: simulate a brain bridge payload="" while IFS= read -r line; do [ -z "$line" ] && break payload="$line" done < /tmp/planckclaw/brain_in echo "brain received: $payload" >&2 printf '{"content":[{"type":"text","text":"Hello!"}],"stop_reason":"end_turn"}\n\n' > /tmp/planckclaw/brain_out ``` -------------------------------- ### FIFO Format: interact_in/interact_out Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Format for communication between Bridge Interact and Agent. Uses tab separation and specific escaping rules for newlines, tabs, and backslashes. ```text {channel_id}\t{text_with_escaped_newlines}\n ``` ```text Example input: 1234567890123456789\tHello how are you?\n ``` ```text Example output: 1234567890123456789\tI'm fine thanks!\nHow about you?\n ``` -------------------------------- ### Anthropic AI Bridge Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Processes prompts from a FIFO, sends them to the Anthropic API, and writes the response back to another FIFO. Handles API errors by returning a timeout error. Requires ANTHROPIC_API_KEY. ```shell #!/bin/sh . ./config.env while true; do # Read payload from brain_in until an empty line (double newline) PAYLOAD="" while IFS= read -r line || [[ -n "$line" ]]; do if [ -z "$line" ]; then break # Empty line signifies end of payload fi PAYLOAD+="$line\n" done < /tmp/planckclaw/brain_in # Remove trailing newline if present PAYLOAD=$(echo -e "$PAYLOAD" | sed '\/\n$$/d') if [ -z "$PAYLOAD" ]; then # If payload is empty after reading, continue to next iteration sleep 0.1 # Prevent busy-waiting continue fi # Send request to Anthropic API RESPONSE=$(curl -s -X POST "https://api.anthropic.com/v1/messages" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d "$PAYLOAD") # Check for success (simplified: assumes non-empty response is success) if [ -n "$RESPONSE" ]; then echo "$RESPONSE\n\n" > /tmp/planckclaw/brain_out else # Handle failure after retries (simplified: return timeout error) echo "{\"error\":\"timeout\"}\n\n" > /tmp/planckclaw/brain_out fi done ``` -------------------------------- ### Discord RECEPTION subprocess Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Handles receiving messages from Discord via WebSocket and processing them. It filters messages by channel and author, then writes them to a FIFO for further processing. Requires DISCORD_BOT_TOKEN and DISCORD_CHANNEL_ID environment variables. ```shell #!/bin/sh . ./config.env umask 077 mkdir -p /tmp/planckclaw mkfifo /tmp/planckclaw/interact_in mkfifo /tmp/planckclaw/interact_out # STARTUP # Get gateway URL URL=$(curl -s "https://discord.com/api/v10/gateway" | jq -r '.url') # Open WebSocket connection websocat --text "$URL/?v=10&encoding=json" | while IFS= read -r line; do # Parse JSON message OP=$(echo "$line" | jq -r '.op') D=$(echo "$line" | jq -c '.d') S=$(echo "$line" | jq -r '.s') # Store sequence number for heartbeats if [ -n "$S" ] && [ "$S" != "null" ]; then LAST_SEQUENCE="$S" fi case $OP in 10) # Hello HEARTBEAT_INTERVAL=$(echo "$D" | jq -r '.heartbeat_interval') # Send Identify payload echo "{"op":2,"d":{"token":"$DISCORD_BOT_TOKEN","intents":512,"properties":{"os":"linux","browser":"planckclaw","device":"planckclaw"}}}" >&2 # Debug echo "{"op":2,"d":{"token":"$DISCORD_BOT_TOKEN","intents":512,"properties":{"os":"linux","browser":"planckclaw","device":"planckclaw"}}}" # Start heartbeat timer (while true; do sleep "$((HEARTBEAT_INTERVAL / 1000))"; echo "{"op":1,"d":$LAST_SEQUENCE}"; done) & # Send heartbeat ;; 0) # Dispatch TYPE=$(echo "$D" | jq -r '.type') if [ "$TYPE" = "MESSAGE_CREATE" ]; then CHANNEL_ID=$(echo "$D" | jq -r '.channel_id') CONTENT=$(echo "$D" | jq -r '.content') AUTHOR_BOT=$(echo "$D" | jq -r '.author.bot') # Ignore bot messages and messages not in the target channel if [ "$AUTHOR_BOT" = "false" ] && [ "$CHANNEL_ID" = "$DISCORD_CHANNEL_ID" ]; then # Escape newlines and tabs for FIFO CONTENT_ESCAPED=$(echo "$CONTENT" | sed 's/\n/\\n/g' | sed 's/\t/\\t/g') echo "$CHANNEL_ID\t$CONTENT_ESCAPED" > /tmp/planckclaw/interact_out fi fi ;; 11) # Heartbeat ACK # No operation needed ;; *) # Other opcodes echo "Received unknown opcode: $OP with data: $D" >&2 ;; esac done # Handle disconnects (simplified: restart after a delay) while true; do sleep 5 echo "Reconnecting..." # Re-run the script logic (simplified for example, a real script would loop or restart) # This part would typically involve re-executing the startup and loop logic # For brevity, we'll just indicate a restart is needed. echo "Restarting connection logic..." # In a real script, you'd likely have a loop that calls functions for startup and main processing. # Example: ./bridge_discord.sh RESTART # For this example, we'll just exit to simulate a restart trigger. exit 1 done ``` -------------------------------- ### Manual Bridge Test: Agent Payload Simulation Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Simulate the agent sending a payload to the bridge's input FIFO for manual testing. The payload is a JSON object representing a message. ```sh # Terminal 1: simulate the agent sending a payload printf '{"model":"test","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}\n\n' > /tmp/planckclaw/brain_in ``` -------------------------------- ### Agent Request Format Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md The agent sends Anthropic Messages API compatible JSON. Ensure all required fields like model, max_tokens, and messages are included. ```json {"model":"claude-haiku-4-5-20241022","max_tokens":1024,"system":"You are helpful.","messages":[{"role":"user","content":"What time is it?"}],"tools":[{"name":"get_time","description":"Get current UTC time","input_schema":{"type":"object","properties":{}}}]} ``` -------------------------------- ### Discord <-> Agent FIFO Format Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Defines the structure for messages exchanged between Discord and the Agent via FIFO. It specifies delimiters and character encoding for channel IDs and text content. ```text {channel_id}\t{text}\n ``` ```text 1234567890123456789\tHello how are you?\n ``` -------------------------------- ### LLM Error Handling: Fatal Error Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Shows the error response written to fifo_llm_res for a fatal error, indicating repeated failures. ```json {\"error\":\"fatal\"}\n\n ``` -------------------------------- ### Bridge LLM to Agent Response (Error) Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Error responses from the bridge, not directly from the API. The agent checks for the root-level 'error' key. ```json {"error":"timeout"} ``` ```json {"error":"fatal"} ``` -------------------------------- ### JSON Error Detection Strategy Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Describes the procedure for detecting an 'error' key within the JSON structure before proceeding with normal content extraction. ```text 1. Enter root object (depth 0) 2. Scan keys at depth 0. If key == "error" → return error flag 3. If key == "content" → proceed with normal extraction ``` -------------------------------- ### Interact Protocol Wire Format Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Defines the structure for messages exchanged between platforms and the agent via the Interact Protocol. Includes channel ID, escaped text, and a newline delimiter. ```text {channel_id} {escaped_text} ``` -------------------------------- ### FIFO Format: brain_in/brain_out Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Format for communication between Agent and Brain Bridge. Uses double newlines as a message delimiter, with JSON always on a single line. ```text {compact JSON}\n\n ``` -------------------------------- ### Discord SEND subprocess Source: https://github.com/frntn/plankclaw/blob/main/SPECS.md Reads messages from a FIFO and sends them to Discord via the REST API. Handles message splitting for Discord's character limit and rate limiting. Requires DISCORD_BOT_TOKEN. ```shell #!/bin/sh . ./config.env while IFS=$'\t' read -r CHANNEL_ID RESPONSE; do # Unescape newlines and tabs RESPONSE_UNESCAPED=$(echo "$RESPONSE" | sed 's/\\n/\n/g' | sed 's/\\t/\t/g') # Discord message character limit is 2000 if [ "${#RESPONSE_UNESCAPED}" -gt 2000 ]; then # Split message into chunks of 1990 characters for i in "$(seq 0 1990 $((${#RESPONSE_UNESCAPED} - 1)))"; do CHUNK=$(echo "$RESPONSE_UNESCAPED" | cut -c "$((i+1))"-"$((i+1990))") curl -X POST "https://discord.com/api/v10/channels/$CHANNEL_ID/messages" \ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"content\":\"$CHUNK\"}" sleep 1 # Small delay between chunks done else # Send message directly curl -X POST "https://discord.com/api/v10/channels/$CHANNEL_ID/messages" \ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"content\":\"$RESPONSE_UNESCAPED\"}" fi # Handle rate limiting (simplified: check for 429 and retry) HTTP_STATUS=$(curl -s -o /dev/null -w '%{http_code}' -X POST "https://discord.com/api/v10/channels/$CHANNEL_ID/messages" \ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"content\":\"$RESPONSE_UNESCAPED\"}") if [ "$HTTP_STATUS" = "429" ]; then RETRY_AFTER=$(curl -s -I -X POST "https://discord.com/api/v10/channels/$CHANNEL_ID/messages" \ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"content\":\"$RESPONSE_UNESCAPED\"}" | grep -i 'Retry-After:' | awk '{print $2}' | tr -d '\r') echo "Rate limited. Retrying after $RETRY_AFTER seconds..." >&2 sleep "$RETRY_AFTER" # Re-send the message (simplified, a real implementation would loop until success or max retries) continue # Retry the current message elif [ "$HTTP_STATUS" != "200" ]; then echo "Error sending message to Discord: HTTP $HTTP_STATUS" >&2 # Log other errors and continue fi done < /tmp/planckclaw/interact_in ``` -------------------------------- ### Brain Protocol Wire Format Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md Specifies the format for messages exchanged between the agent and LLM providers via the Brain Protocol. Uses compact JSON followed by a double newline delimiter. ```text {compact_json} ``` -------------------------------- ### Bridge Error Format Source: https://github.com/frntn/plankclaw/blob/main/PROTOCOL.md On unrecoverable failure after retries, the bridge returns a JSON object with an 'error' key. This indicates a timeout or other critical issue. ```json {"error":"timeout"} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.