HarnessClaw Engine
An LLM programming assistant engine built with Go. It provides capabilities via the WebSocket protocol, supporting multi-turn dialogues, tool calling, permission control, and skill extension.
Architecture Overview
┌───────────-──┐ ┌─────────────┐ ┌─────────────┐
│ WebSocket │ │ HTTP │ │ Feishu │
│ Channel │ │ Channel │ │ Channel │
└──────┬───────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└──────────────────┼──────────────────┘
▼
┌──────────────────┐
│Router + Middleware│ Auth / RateLimit / Logging
└────────┬─────────┘
▼
┌──────────────────┐
│ Query Engine │ 5-Phase Loop
│ (queryloop.go) │ Preprocessing → LLM Streaming → Error Recovery
└───┬──────────┬───┘ → Tool Execution → Continuation Check
│ │
┌─────▼──-─┐ ┌──▼──────────┐
│ Provider │ │ Tool System │
│ (LLM) │ │ 7 Built-in │
└───────-──┘ └─────────────┘
Dependency Direction: Channel → Router → Engine → Provider / Tool (Unidirectional, no circular dependencies)
Core Features
- 5-Phase Query Loop — Preprocessing (Auto-compaction) → LLM Streaming Call → Error Recovery (Exponential Backoff) → Tool Execution (Parallel/Serial) → Continuation Check
- WebSocket Protocol v2.2 (Card Model) — UI-first streaming: 8 actions (
card.add/set/append/tick/close+prompt.user/reply+session.event) × 13 card kinds; server-side & client-side tool execution, permission / question / plan-review prompts, and crash-recovery of unanswered prompts - 7 Built-in Tools — Bash, FileRead, FileEdit, FileWrite, Grep, Glob, WebFetch
- 6-Step Permission Pipeline — DenyRule → ToolCheckPerm → BypassMode → AlwaysAllowRule → ReadOnlyAutoAllow → ModeDefault, supporting 6 permission modes
- Skill System — Loads skills from
SKILL.mdfiles, supporting YAML frontmatter, parameter substitution, and priority override - Multi-Provider Support — Direct Anthropic SSE client + Bifrost Multi-Provider adapter (Anthropic/OpenAI/Bedrock/Vertex)
- Context Compaction — LLM-based conversation summarization + Circuit breaker pattern, automatically triggered when token usage reaches the threshold
- Session Management — Thread-safe session state, multi-connection fan-out, idle timeout reclamation
Project Structure
go_rebuild/
├── cmd/server/ # Entry point & Integration tests
│ ├── main.go # 11-step startup process
│ └── main_test.go # E2E tests (build tag: integration)
├── configs/
│ └── config.yaml # Default configuration
├── internal/
│ ├── channel/ # Multi-protocol access layer (WebSocket / HTTP / Feishu)
│ ├── command/ # Command registration & Priority system
│ ├── config/ # Viper configuration management (50+ defaults)
│ ├── engine/ # Core query engine
│ │ ├── queryloop.go # QueryEngine main loop (831 lines)
│ │ ├── executor.go # Parallel/Serial tool executor
│ │ ├── compact/ # LLM context compaction
│ │ ├── context/ # System prompt assembly
│ │ └── session/ # Session state & Lifecycle
│ ├── event/ # In-process pub/sub event bus
│ ├── permission/ # 6-step permission pipeline (6 modes)
│ ├── provider/ # LLM Provider abstraction
│ │ ├── anthropic/ # Direct Anthropic SSE client
│ │ ├── bifrost/ # Multi-Provider adapter
│ │ └── retry/ # Exponential backoff + 529 overload switching
│ ├── router/ # Message routing + Middleware chain
│ ├── skill/ # SKILL.md loading & Parameter substitution
│ ├── storage/ # Storage interfaces (Memory implementation)
│ └── tool/ # Tool system
│ ├── tool.go # Tool interface + 10 extension interfaces
│ ├── registry.go # Thread-safe tool registry
│ ├── pool.go # Immutable per-query tool pool
│ └── bash/fileread/fileedit/filewrite/grep/glob/webfetch/skilltool/
├── pkg/
│ ├── types/ # Shared types (Message, Event, ToolCall, Context)
│ └── errors/ # Domain errors (16 error codes)
├── docs/
│ ├── protocols/ # WebSocket protocol specification (v2.2)
├── Makefile # Build/Run/Test/Lint
└── go.mod # Go 1.26.1
Quick Start
Prerequisites
- Go 1.26+
- (Optional) golangci-lint — For code linting
- (Optional) ripgrep — Runtime dependency for the Grep tool
Build & Run
# Build
make build # Outputs to ./dist/harnessclaw-engine
# Run (using default configuration)
make run # go run ./cmd/server -config ./configs/config.yaml
# Run directly with a specific configuration file
./dist/harnessclaw-engine -config ./configs/config.yaml
Testing
# Unit tests
make test # go test ./... -v -race -count=1
# Coverage report
make test-cover # Generates coverage.html
# Integration tests (requires real LLM API)
go test -tags=integration ./cmd/server/ -v
go test -tags=integration ./internal/provider/bifrost/ -v
Other Commands
make fmt # Format code
make tidy # Tidy go.mod
make lint # Run linters
make vuln # Scan for vulnerabilities
make clean # Clean build artifacts
Configuration
The configuration file is located at configs/config.yaml. Main configuration items:
| Configuration Item | Description | Default Value |
|---|---|---|
server.port | HTTP server port | 8080 |
channels.websocket.port | WebSocket port | 8081 |
channels.websocket.path | WebSocket path | /v1/ws |
llm.default_provider | LLM Provider | anthropic |
llm.providers.anthropic.model | Model name | astron-code-latest |
engine.max_turns | Max tool calls per turn | 50 |
engine.auto_compact_threshold | Token ratio threshold for auto-compaction | 0.8 |
session.idle_timeout | Session idle timeout | 30m |
permission.mode | Permission mode | default |
tools.* | Individual tool toggles | All true |
WebSocket Protocol
Connection Address: ws://host:8081/v1/ws
The protocol is a UI-first card model: the engine streams cards (a turn, a message, a tool call, a sub-agent, …) that are opened, appended to, and closed, rather than a flat event log.
Session Lifecycle
Client Server
│ │
│── WebSocket upgrade ────────────────────>│
│<──────────────── 101 Switching ─────────│
│<──── session.event (kind=opened) ───────│ handshake + capabilities
│ │
│── user.message ─────────────────────────>│
│<──────────────── card.add ──────────────│ open a card (turn / message / tool / …)
│<──────────────── card.append ───────────│ stream content (channel: text / tool_input)
│<──── prompt.user (permission / … ) ─────│ engine asks; blocks until answered
│── prompt.user_response ─────────────────>│
│<──────────────── card.close ────────────│ card done (+ metrics: tokens, cost)
│<──────────── card.close (kind=turn) ────│ turn finished
│ │
│── session.interrupt (trace_id) ─────────>│ interrupt an in-flight turn
│── session.resume (last_seq) ───────────>│ reconnect & replay missed events
For a copy-paste client, see the Usage Examples; for the full wire contract, see docs/protocols/websocket.md.
Documentation
📞 Support
- 💬 Community Discussion: GitHub Discussions
- 🐛 Bug Reports: Issues
- 👾 Discord: Join our server
- 👥 WeChat Work Group:

License
Apache-2.0 License. See LICENSE for details.