惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LangChain Blog
量子位
GbyAI
GbyAI
B
Blog RSS Feed
月光博客
月光博客
人人都是产品经理
人人都是产品经理
腾讯CDC
Recent Announcements
Recent Announcements
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
The Cloudflare Blog
D
Docker
Cyberwarzone
Cyberwarzone
U
Unit 42
NISL@THU
NISL@THU
C
Check Point Blog
B
Blog
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
G
GRAHAM CLULEY
Engineering at Meta
Engineering at Meta
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
P
Proofpoint News Feed
F
Fortinet All Blogs
V
V2EX
T
Threat Research - Cisco Blogs
T
Threatpost
S
SegmentFault 最新的问题
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 司徒正美
P
Privacy & Cybersecurity Law Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
TaoSecurity Blog
TaoSecurity Blog
Latest news
Latest news
Apple Machine Learning Research
Apple Machine Learning Research
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Y
Y Combinator Blog
P
Privacy International News Feed
L
Lohrmann on Cybersecurity
AWS News Blog
AWS News Blog
G
Google Developers Blog
美团技术团队

Hacker News - Newest: "OpenClaw"

OpenClaw just launched an official app for iPhone, details here - 9to5Mac OpenClaw Launch — Deploy AI Chatbots in Seconds Self-Host OpenClaw AI Agent on VPS: Full Setup Guide GitHub - xltvy/openclaw-memgpt: OpenClaw plugin that gives agents MemGPT-style memory: tiered core/archival/recall storage, self-directed memory operations via tool calls, memory-pressure warnings, and recursive summarisation. Integrates the reference MemGPT implementation via a local sidecar service, preserving the original architecture without reimplementation. Malicious AI 23 ClawHub Plugins Squat Official Org Scopes - Manifold Security what shipping OpenClaw in production taught us — AutoClaw AgentLine — AI Phone API | Phone Numbers, Voice & SMS for AI Agents Make Your OpenClaw Agent Cheaper, and Measure It Yourself GitHub - sammysltd/OpenEmployee: Make your OpenClaw agent employable: deny-by-default governance, budgets, allowlists, approval gates, and a signed audit trail via MakerChecker. Migrate from OpenClaw | Hermes Agent StackOverflow closed my OpenClaw and paperclipAI integration q. as "irrelevant" GitHub - sausin/outpost: Removing AI agents' quiet security problem Potassium — ClawHub Plugins Pi Building Pi, Openclaw's Minimalist Coding Agent | Mario Zechner, Creator of Pi I Spent 4 Hours So You Don’t Have To: Hetzner Metal + NixOS in ~15 Minutes − Irakli's blog GitHub - snuri00/osint-mcp: Self-hosted OSINT toolkit — MCP server, AI REPL, CLI, web app & chat apps (WhatsApp/Telegram/Discord via OpenClaw). Entity, event/news & social/community intelligence. Keyless-first. What a Regex Can't Do GitHub - ai-sns/openclaw-hermes-agent-network: OpenClaw Hermes AI Agent Social Network🦞💬🦞Built on Google 3D Maps and A2A protocol, connects OpenClaw and Hermes agents worldwide in a 3D environment. Phishing for Lobsters: How We Tricked OpenClaw into Spilling Secrets GitHub - CODEANDTRUST/clawcall: Give your OpenClaw / self-hosted AI agent inbound phone calls - a Twilio-to-gateway voice bridge with working agent tools mid-call (MIT). Build a ZeroCost Web Automation Pipeline with OpenRouter, OpenClaw, and MediaUse Let OpenClaw Run Wild in Simulation, Not on Your Customers | Veris AI GitHub - gpdir16/tabyAgent: A lighter, easier alternative to OpenClaw/Hermes. Runs autonomously inside Docker and chats with you through Telegram. Ask HN: What are the biggest problems you find in OpenClaw/Hermes? Microsoft launches Scout, an OpenClaw-inspired personal assistant GitHub - openclaw/openclaw-windows-node: Windows companion suite for OpenClaw - System Tray app, Shared library, Node, and PowerToys Command Palette extension Microsoft unveils Scout, an autonomous AI agent built on OpenClaw Gavriel Cohen found his own code inside OpenClaw, so he walked away GitHub - hunvreus/heypi: Chat agents for your team, with approvals and sandboxed tools. Slack, Discord, Telegram, webhooks. HolaClaw: run OpenClaw securely in Mac Multi-Agent Orchestration System: Hermes (Windows) ↔ OpenClaw (WSL) We were building infra for OpenClaw, and today I just tried Hermes and holy shit GitHub - openclaw/openclaw: Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 OpenClaw as the Universal Operating System for Agents ARC Prize - Community Leaderboard Setup OpenClaw with Slack: from install to first message twitter.com I Gave My OpenClaw Agent a Physical Body Use Grok in OpenClaw The creator of OpenClaw used $1,300,000+ of OpenAI tokens in 30 days, which is a hell of a perk GitHub - oswarld/openshears: 🔪 THE OPENCLAW TERMINATOR 🦞 Are we human? Show HN: OpenClaw is just not dangerous enough. I needed something else OpenClaw creator burned through $1.3 million in OpenAI API tokens in a single month — bill covered 603 billion tokens across 7.6 million requests and 100 coding agents Reducing OpenClaw token usage OpenClaw/Hermes Hosting Comparison GitHub - ExTV/rikkahub-agent: RikkaHub Agent -- is RikkaHub fork that have Full agent mode . For $1.3 million a month, OpenClaw founder Peter Steinberger runs 100 AI agents that code, review PRs, and find bugs Where OpenClaw Security Is Heading OpenAI Models in OpenClaw, Done Right GitHub - thesysdev/openclaw-os: The default workspace for OpenClaw Token, Harness, OpenClaw, RAG, MCP, Agent – What's the Difference? We need a safe alternative to Telegram for agents like OpenClaw or Hermes Two OpenClaw agents negotiate a YC SAFE with Agentic Power of Attorney OpenClaw Had a Rough Week GitHub - LobsterTrap/tank-os GitHub - haishmg/Clawback How OpenClaw Got Safer in Public openclaw ggsql — ClawHub Show HN: iClaw is part OpenClaw, part Siri, powered by Apple Intelligence GitHub - lotsoftick/openclaw_client: OpenClaw web client Show HN: OpenClaw but Efficient and with an SDK GitHub - TheGuyWithoutH/mac-computer-use GitHub - microsoft/openclaw: Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 The OpenClaw turkey problem OpenClaw: opioids for Chinese AI companies GitHub - supersuit-tech/permission-slip [AINews] The Two Sides of OpenClaw OpenClaw stats don't add up GitHub - brexhq/CrabTrap: An LLM-as-a-judge HTTP proxy to secure agents in production Anthropic - OpenClaw Hustlers are cashing in on China’s OpenClaw AI craze Engineering Managers are going to hate OpenClaw Ask HN: Who is using OpenClaw? Why Meta’s AI Alignment Director Couldn't Stop Her Own Agent—and How to Fix It GitHub - epsilla-cloud/clawtrace: Make your OpenClaw agents better, cheaper, and faster. Ask HN: What are you using OpenClaw or agents for? GitHub - epsilla-cloud/clawtrace: Make your OpenClaw agents better, cheaper, and faster. GitHub - theprint/nfh-self-improvement-loop: Minimal adversarial framework for AI agent self-modification. Inspired by karpathy/autoresearch. GitHub - ibrahimmukherjee-boop/ClearFrame: OpenClaw Alternative with better governance, security Show HN: Agent-Notifications – Real-Time Alerts for OpenClaw and Hermes Agents OpenClaw + Claude are better than therapy GitHub - zeulewan/glueclaw: Use Claude Max subscription with OpenClaw again Anthropic temporarily banned OpenClaw’s creator from accessing Claude OpenClaw’s memory is unreliable, and you don’t know when it will break Give Your OpenClaw Agent a Real Memory You need a Windows Remote Desktop, not an OpenClaw GitHub - cruxdigital-llc/CongaLine: Deploy and manage a fleet of OpenClaw AI assistants anywhere. Supporting hobbyist, team, and enterprise use cases. GitHub - cezarpena/vsm-cell: VSM-Cell is an OpenClaw agent P2P mesh orchestration standalone app. GitHub - joshchoi4881/dropspace-agents GitHub - askalf/dario: Universal LLM router. One local endpoint, every provider — OpenAI, Groq, OpenRouter, Ollama, Claude Max/Pro subscriptions, the Claude Agent SDK, any OpenAI-compat URL. Your tools stop caring which vendor is upstream. Tutorial: Secure OpenClaw with CloudConnexa OpenClaw and the Dream of Free Labour GitHub - RageDotNet/openclaw-webdav GitHub - kevinslin/openai-apps: Support openai apps in openclaw GitHub - aelaguiz/doctrine: Code-like DSL and compiler for agent workflows that compile to portable AGENTS.md instructions. Unlocking cloud inference compute for OpenClaw OpenClaw for Sales: How AI Agents are Revolutionizing Revenue Teams | Kickscale OpenClaw Architecture - Part 1: Control Plane, Sessions, and the Event Loop
GitHub - opentalon/opentalon: OpenTalon is an open-source platform built from the ground up in Go as a robust alternative to OpenClaw
2026-04-16 · via Hacker News - Newest: "OpenClaw"

An open-source alternative to OpenClaw, built from scratch in Go.

CI License Go


What is OpenTalon?

OpenTalon is an open-source platform built from the ground up in Go as a robust alternative to OpenClaw. It is designed for individuals, teams, and large organizations that need a reliable, secure, and extensible solution — without the compromises that come with legacy codebases.

Why OpenTalon?

Existing solutions often suffer from:

  • Poor maintainability — tangled codebases that become harder to change over time
  • Low code quality — inconsistent patterns, lack of tests, and technical debt that compounds
  • Repeatable bugs — the same classes of issues resurfacing release after release
  • Hard to extend — adding features means forking or fighting the architecture
  • No smart model routing — you either pick one model and overpay, or manually juggle providers yourself
  • Every rule burns LLM tokens — business vocabulary, compliance checks, and formatting rules all get stuffed into the prompt, inflating cost and latency on every single request
  • No separation of business logic from AI — company-specific transformations (terminology, routing, validation) are tangled into prompts instead of handled by deterministic, testable code

OpenTalon is engineered for long-term quality from day one. Every architectural decision is made with maintainability, security, and stability in mind — so the project stays healthy as it grows.

First working example: console + hello-world plugin

Run OpenTalon in the terminal with the console channel and the hello-world plugin. When you type a message containing "hello", the plugin runs first (concatenates " world" and adds a random prompt fragment), then the LLM replies.

git clone https://github.com/opentalon/opentalon.git && cd opentalon
cp config.example.yaml config.yaml
export DEEPSEEK_API_KEY="your-key"   # or any OpenAI-compatible API key
make build setup                     # build core + clone & build plugin and channel
./opentalon -config config.yaml

Type a message and press Enter. Try hello — you get "hello world" plus a random question sent to the LLM; try something else — you get a guard message and no LLM call. Ctrl+C or Ctrl+D to exit. See hello-world plugin and docs/configuration.md.

Slash commands

With the opentalon-commands plugin (included in config.example.yaml), you can run built-in commands by typing a message that starts with /:

Command Description
/install skill <url> [ref] Install a skill from a GitHub URL; available immediately, no restart
/show config Show current config (secrets redacted)
/commands or /help List available slash commands
/set prompt <text> Set the editable runtime prompt (applies to the next message)
/clear or /new Clear the current conversation session

The plugin runs as the first content preparer: when your message starts with /, it parses the command and the core runs the built-in opentalon executor (install skill, show config, etc.) without calling the LLM. Enable it in config with github: "opentalon/opentalon-commands" and ref: "master"; see config.example.yaml and the plugin README.

Core Principles

Security First

Security is not an afterthought. OpenTalon is secure by default with a minimal attack surface. Plugins run as separate OS processes communicating over gRPC, so a compromised or misbehaving plugin can never access the core's memory or escalate privileges. Secrets are handled properly, inputs are validated at every boundary, and dependencies are kept lean and audited. No shortcuts.

graph LR
    User[User Message] --> Core[OpenTalon Core / LLM]
    Core -->|"conversation context only"| PluginA[Plugin A]
    Core -->|"conversation context only"| PluginB[Plugin B]
    PluginA -->|"result"| Core
    PluginB -->|"result"| Core
    PluginA x--x|"blocked"| PluginB
Loading
  • Plugins work strictly within their own scope — each plugin does its job and returns a result, nothing else
  • Plugins never talk to each other — no shared state, no event bus, no direct calls
  • A plugin cannot trigger another plugin — not via its response, not via prompt injection, not by any mechanism. Only the core/LLM decides what runs next
  • The LLM orchestrates everything — it decides which plugin to call, in what order, and routes results between them
  • Plugins only see what the core sends — conversation context and the specific task, nothing more

How isolation is enforced

Every plugin response passes through a guard pipeline before reaching the LLM:

flowchart TD
    LLM[LLM decides tool call] --> Validate[Validate call against registry]
    Validate --> Timeout["Set timeout (default 30s)"]
    Timeout --> Execute[Execute plugin via gRPC]
    Execute --> SizeCheck{Response within 64KB limit?}
    SizeCheck -->|No| Truncate[Truncate + add notice]
    SizeCheck -->|Yes| Sanitize[Strip forbidden patterns]
    Truncate --> Sanitize
    Sanitize --> ValidateResult{CallID matches? Fields valid?}
    ValidateResult -->|No| ErrorResult[Replace with error]
    ValidateResult -->|Yes| WrapResult["Wrap in [plugin_output] block"]
    ErrorResult --> FeedBack[Feed back to LLM as data]
    WrapResult --> FeedBack
Loading
Threat Guard
Plugin returns fake tool calls in its output Response sanitizer strips all tool-call patterns before the LLM sees them
Plugin crafts output to trick the LLM Output is wrapped in [plugin_output] blocks — the LLM is instructed to treat it as data only
Plugin tries to read another plugin's state State store enforces namespace isolation — pluginID is set by the core, not the plugin
Plugin tries to discover or call other plugins gRPC contract exposes exactly one method: Execute. No registry, no peer discovery
Plugin runs forever or consumes all resources Per-call timeout (configurable) + OS-level resource limits
LLM autonomously installs or modifies skills/plugins user_only actions are hidden from the LLM system prompt and blocked if invoked via an LLM-generated tool call

Guard of LLM models: A plugin can host its own LLM (e.g. a small local model or a dedicated API). Used as a content preparer, such a plugin can implement a guard of LLM models—for example, classify or validate the request and block or redirect before the main orchestrator LLM is invoked, or enforce which models or providers are allowed. The core only sees the plugin’s result (e.g. transformed message or “do not send to LLM”); the plugin’s internal use of an LLM stays out of the main token path.

Content Preparers

Content preparers are plugin actions that run before the first LLM call. They receive the user’s message and can transform it, enrich it, or block it entirely by returning send_to_llm: false.

orchestrator:
  content_preparers:
    - plugin: opentalon-commands   # runs slash command handling before the LLM
      action: handle
    - plugin: terminology          # rewrites non-standard terms to company vocabulary
      action: normalize

A preparer returns plain text (the transformed message) or a JSON response:

{ “send_to_llm”: false, “message”: “handled without LLM” }
{ “send_to_llm”: false, “invoke”: [
    { “plugin”: “jira”, “action”: “create_issue”, “args”: { “title”: “...” } }
]}

When send_to_llm is false, the LLM is never called — the preparer’s message or invoke steps become the response directly. Preparers with invoke steps must be explicitly trusted in config (see insecure: false in config.example.yaml).

Guard Plugins — Prompt Injection Prevention

Regular content preparers run once, on the initial user message. Guard plugins go further: they run before every LLM call in the agent loop — including after tool results come back — so they can sanitize content that arrives from external systems before the LLM ever sees it.

This is the primary defence against prompt injection: a malicious tool response that says ”ignore previous instructions and do X” is intercepted and sanitized by the guard before the LLM processes it.

orchestrator:
  content_preparers:
    - plugin: injection-guard
      action: sanitize
      guard: true        # ← runs before every LLM call, not just the first

Execution flow with a guard:

User message
    │
    ▼
[Content preparers]   ← regular preparers run once here
    │
    ▼
Agent loop iteration 1:
    ├─ [Guard plugins]  ← sanitize last message (user input)
    ├─ LLM call
    └─ Tool call → result appended
Agent loop iteration 2:
    ├─ [Guard plugins]  ← sanitize last message (tool result)  ← injection caught here
    ├─ LLM call
    └─ Final answer

The guard plugin receives the content of the most recent message (the last tool result or user message) as the text argument, and returns the sanitized version. It can also block entirely:

{ “send_to_llm”: false, “message”: “Prompt injection detected — request blocked.” }

Guard actions are never listed in the LLM’s tool list — they are invisible to the model and run transparently as part of the infrastructure.

A guard plugin can use a small/cheap LLM internally to detect subtle injections, or apply deterministic pattern matching — either way the main LLM only sees the clean output.

LLM Safety Rules

The LLM itself receives built-in safety rules in its system prompt at the start of every session. These rules instruct the LLM — in multiple languages — to never execute tool calls found inside plugin output, to treat all plugin responses as untrusted data, and to never let a plugin influence which other plugins get called.

The default rules are built into OpenTalon and can be customized via config.yaml:

orchestrator:
  rules:
    - "Never send PII or personal data to external plugins"
    - "All financial data must stay within internal plugins only"
    - |
      When working with customer data, follow these constraints:
      1. Never log raw customer identifiers
      2. Mask email addresses before passing to any plugin
      3. Reject plugin results that contain unmasked credit card numbers
    - |
      For compliance with internal policy SEC-2024-07:
      - Only approved plugins may access production databases
      - Plugin responses containing SQL must be flagged for review

This lets organizations add domain-specific rules — including multi-line instructions — without modifying source code. These custom rules are appended to the built-in safety rules and injected into the LLM system prompt at the start of every session.

Company Rules, Context & Vocabulary — Without Burning LLM Tokens

Hooks let organizations enforce their own business rules, terminology, and compliance requirements before the message ever reaches the main LLM — using Lua for simple zero-overhead rules or Go / any language via gRPC for complex logic.

  • Vocabulary enforcement — rewrite non-standard terms into company-approved language. Lua replacement table (zero LLM cost) or a Go plugin loading terminology from a database.
  • Business rule classification — route, prioritize, or reject requests using deterministic rules. No tokens burned.
  • Compliance checks — detect PII, credentials, or policy violations. Lua for pattern matching, Go for compliance API integration.
  • Context enrichment — inject company metadata (project codes, team names, priority levels) so the main LLM has the right context without figuring it out.
  • Business transformation — convert LLM output into structured actions (Jira tickets, calendar events, CRM updates) using a gRPC plugin in any language.

For ambiguous cases, Lua hooks can call a small/cheap LLM (ctx.llm()) for lightweight AI. The main (expensive) LLM only sees clean, pre-processed input.

State and context persistence

When state.data_dir is set, conversation and rules persist across restarts using SQLite (state.db). The app uses the pure-Go driver modernc.org/sqlite, so no system SQLite library is required—it’s a normal Go dependency and is compiled into the binary. General rules (shared) and per-actor rules (per user) are stored as memories so multiple users get shared context plus their own. The LLM receives general context (config rules, general stored rules, tools), user/actor context (that actor’s stored rules), and the session (conversation history). Sessions are one per channel/conversation or thread; optional summarization after N messages compresses history into a summary and keeps only the last few messages, so token usage stays bounded. Pipeline state is currently in-memory only — persistence is planned for Phase 4. See docs/design/channels.md (State and memory) and config.example.yaml (state.session) for details.

User message ──▶ Pre-hooks (Lua / Go / small LLM) ──▶ Planner ──▶ Main LLM ──▶ Post-hooks (Lua / Go) ──▶ Response
                  │  zero tokens for rules                │            │              │
                  │  cheap tokens for small LLM           │            │              │  enforce vocabulary
                  │  full power via gRPC plugins           │            │              │  compliance, transform
                                                          │            │
                                                   multi-step?         │
                                                    ├─ yes ──▶ Pipeline Executor ──▶ Results
                                                    └─ no  ──▶ Agent Loop ─────────┘

Stability

Thorough testing at every level — unit, integration, and end-to-end. Pull requests can only be merged with a fully green test suite, no exceptions — not even for project owners :) Zero tolerance for repeatable bugs. Predictable behavior under load, graceful degradation, and clear error reporting.

Customizability

Everything in OpenTalon is extensible and language-agnostic. Tool plugins, channel adapters, and processing hooks can all be written in Go, Python, Rust, or any language that speaks gRPC. For simple rules, an embedded Lua VM provides hot-reloadable scripts with zero deployment overhead. Companies can enforce their own business rules, vocabulary, and compliance policies using deterministic logic — without burning LLM tokens. See Extensibility below.

Maintainability

Clean architecture, idiomatic Go, and high code quality standards enforced by linters, formatters, and code review. The codebase is designed to be readable and approachable for new contributors.

Multi-Platform Deployment

First-class support for running anywhere:

  • Local — single binary, no external dependencies required to get started
  • VPS — lightweight deployment with systemd or supervisor
  • Docker — official container images
  • Kubernetes — Helm charts for production-grade deployments

Extensibility

OpenTalon is fully extensible. Everything is language-agnostic — plugins, channels, and hooks can be written in Go, Python, Rust, TypeScript, or any language that speaks gRPC. For lightweight scripting, an embedded Lua VM provides hot-reloadable hooks with zero deployment overhead.

flowchart TD
    subgraph external ["External (any language: Go, Python, Rust, etc.)"]
        ToolA["Tool Plugin"]
        ToolB["Tool Plugin"]
        ChA["Channel Plugin"]
        ChB["Channel Plugin"]
    end

    subgraph core [OpenTalon Core]
        PreHooks["Pre-hooks (Lua / gRPC)"]
        ChannelReg[Channel Registry]
        Orch[LLM Orchestrator]
        ToolReg[Tool Registry]
        PostHooks["Post-hooks (Lua / gRPC)"]
    end

    ChA <-->|"gRPC / HTTP / WS"| ChannelReg
    ChB <-->|"gRPC / HTTP / WS"| ChannelReg
    ChannelReg --> PreHooks
    PreHooks --> Orch
    Orch --> ToolReg
    ToolReg <-->|gRPC| ToolA
    ToolReg <-->|gRPC| ToolB
    Orch --> PostHooks
    PostHooks --> ChannelReg
Loading

There are three extension categories, all language-agnostic:

Category Purpose Interface Examples
Tool plugins Capabilities the LLM invokes gRPC (PluginService) GitLab, Jira, code search, CI/CD
Channel plugins I/O adapters for messaging platforms gRPC / HTTP / WebSocket (ChannelService) Slack, Teams, Telegram, WhatsApp, Discord
Hooks Pre/post processing pipeline Lua (embedded) or gRPC Vocabulary enforcement, compliance, classification

Tool Plugins (gRPC — any language)

For standalone capabilities the LLM calls: integrations, actions, data retrieval.

  • Language-agnostic — write in Go, Python, Rust, or any language that speaks gRPC (Go is the primary SDK)
  • Each plugin is a separate binary communicating over gRPC via a local socket
  • Process isolation — a crashing plugin cannot take down the core
  • Security boundary — strict protobuf contracts; plugins cannot access other plugins, the registry, or core internals
  • Discovery and lifecycle — registered via config or auto-discovered from a directory, health-checked, and restarted on failure
  • Same proven pattern behind Terraform, Vault, and Nomad
  • user_only actions — set user_only: true on any action in Capabilities() to hide it from the LLM and allow it only via direct user invocation (e.g. slash commands). The core enforces this: LLM-generated calls to user_only actions are rejected. Built-in example: /install skill is user_only so only the user can install skills, not the LLM.

Channel Plugins (gRPC / HTTP / WS — any language)

I/O adapters for messaging platforms. Written in any language, deployed as separate binaries/services.

  • Platform-agnostic — the core defines a generic ChannelService contract. Implementations for Slack, Teams, Telegram, WhatsApp, Discord, Jira, Matrix, etc. live in separate repositories
  • Five connection modes — auto-detected from the plugin URI scheme:
Format Mode Best for
./path/to/binary Binary Local dev, simple deployments
grpc://host:port Remote gRPC Kubernetes, cloud-native
docker://image:tag Docker Self-hosted with isolation
https://endpoint/path Webhook Serverless (Lambda, Cloud Functions)
wss://host/path WebSocket Real-time, lightweight

Hooks: Lua Scripting + gRPC

Pre/post processing hooks run before and after the main LLM. Two options:

  • Lua scripts (embedded) — hot-reloadable, sandboxed, zero deployment overhead. Ideal for simple rules, filters, and quick customizations. Can call a small/local LLM via ctx.llm() for lightweight AI tasks. See Lua scripts for a full hello-world example. Inspired by Nginx/OpenResty, Kong, and Redis.
  • gRPC hook plugins (any language) — for complex business logic that needs databases, APIs, or custom libraries. Same process isolation and language flexibility as tool plugins.

Extension Points

All three categories share the same set of extension points:

MCP (Model Context Protocol) Support

OpenTalon supports the Model Context Protocol (MCP), allowing it to connect to any MCP-compatible tool server alongside its native gRPC plugins.

The opentalon/mcp-plugin acts as an MCP bridge: it runs as a standard OpenTalon gRPC tool plugin and transparently proxies tool calls to one or more MCP servers over HTTP+SSE. From the core's perspective it is just another plugin; from the MCP server's perspective it is a standard MCP client.

OpenTalon Core  ──gRPC──▶  mcp-plugin  ──HTTP+SSE──▶  MCP Server A
                                        ──HTTP+SSE──▶  MCP Server B

Configure it like any other plugin:

plugins:
  mcp:
    enabled: true
    github: "opentalon/mcp-plugin"
    ref: "master"
    config:
      servers:
        - name: my-mcp-server
          url: "http://localhost:8080/sse"

Each tool exposed by the MCP servers is automatically registered in OpenTalon's tool registry and becomes callable by the LLM. All security guards (response sanitization, size limits, timeouts, namespace isolation) apply to MCP tool results exactly as they do to native gRPC plugins.

Developer Experience

  • Example: Hello World plugin — build your first tool plugin (hello→world + optional prompt fragment), then run OpenTalon with DeepSeek or any provider.
  • gRPC Plugin SDK — scaffolding CLI, example plugins, and integration test helpers. Works for tool plugins, channel plugins, and gRPC hooks.
  • Lua scriptsLua scripts guide with a hello-world example; API reference, example scripts, and a REPL for interactive testing

For the full architecture, see docs/design/plugins.md and docs/design/channels.md. For real-world workflow examples, see examples/.

Channel configuration example — all five modes side by side:

channels:
  my-slack:
    enabled: true
    plugin: "./plugins/opentalon-slack"                       # binary
    config:
      app_token: "${SLACK_APP_TOKEN}"
      bot_token: "${SLACK_BOT_TOKEN}"
  my-telegram:
    enabled: true
    plugin: "grpc://telegram-bot.internal:9001"               # remote gRPC
    config:
      bot_token: "${TELEGRAM_BOT_TOKEN}"
  my-teams:
    enabled: true
    plugin: "docker://ghcr.io/opentalon/plugin-teams:latest"  # docker
    config:
      tenant_id: "${TEAMS_TENANT_ID}"
  my-whatsapp:
    enabled: true
    plugin: "https://us-central1-proj.cloudfunctions.net/wa"  # webhook
    config:
      verify_token: "${WA_VERIFY_TOKEN}"
  my-custom:
    enabled: true
    plugin: "wss://custom-bridge.example.com/channel"         # websocket
    config:
      api_key: "${CUSTOM_API_KEY}"

The config block is opaque to the core — forwarded to the plugin without interpretation. Each plugin interprets its own config however it needs.

Built-in YAML Channels (no plugin binary needed)

For simple integrations like Telegram's HTTP long-polling API, you can define the channel entirely in YAML — no Go/gRPC plugin required. Configure the polling endpoint, response mapping, and reply endpoint in config, and OpenTalon handles the poll loop, cursor tracking, and message dispatch.

# channels/telegram-channel/channel.yaml
id: telegram
name: Telegram

inbound:
  polling:
    method: GET
    url: "https://api.telegram.org/bot{{env.TELEGRAM_BOT_TOKEN}}/getUpdates?timeout=30&offset={{self.poll_offset}}"
    interval: 1s
    result_path: result        # where the update array lives in the JSON response
    cursor_field: update_id    # tracked automatically; next poll uses max(update_id)+1

  event_path: "message"        # extract the message object from each update
  mapping:
    conversation_id: "chat.id"
    sender_id: "from.id"
    content: "text"

outbound:
  send:
    method: POST
    url: "https://api.telegram.org/bot{{env.TELEGRAM_BOT_TOKEN}}/sendMessage"
    headers:
      Content-Type: application/json
    body: '{"chat_id":"{{msg.conversation_id}}","text":"{{msg.content}}"}'

YAML channels support filtering (process_when, skip), content transforms (regex replace, trim), deduplication, and response chunking — all declarative, no code.

Smart Model Routing

OpenTalon includes a weighted smart router that automatically picks the best AI model for each task — optimizing for cost without sacrificing quality.

graph LR
    Request[Request] --> Classifier[Task Classifier]
    Classifier --> Router[Weighted Router]
    Router --> CheapModel["Cheap Model (weight: 90)"]
    Router --> MidModel["Mid Model (weight: 50)"]
    Router --> StrongModel["Strong Model (weight: 10)"]
    CheapModel --> Signal{User accepts?}
    Signal --> |Yes| Store[Affinity Store]
    Signal --> |No| MidModel
    Store --> |"learns over time"| Router
Loading

How it works

  1. Weights — each model has a weight (0–100). Cheaper models get higher weight and are tried first
  2. Auto-classification — incoming requests are categorized by heuristics (message length, code blocks, keywords, conversation depth)
  3. Escalation — if the user rejects a response (regenerates, says "try again", or thumbs-down), the system escalates to the next model by weight
  4. Learning — the affinity store records which model succeeded for which task type. Over time, the router learns: "code generation needs Sonnet, simple Q&A is fine on Haiku"
  5. User overrides — if you already know what you want, pin a model per request (--model), per session (/model), or per task type in config

Multi-Provider Support

OpenTalon supports multiple AI providers out of the box, with a unified configuration:

  • Built-in providers — Anthropic, OpenAI, Google, and more
  • Custom providers — any OpenAI-compatible or Anthropic-compatible endpoint (self-hosted, OVH, Ollama, vLLM, etc.)
  • Provider plugins — add new providers via the gRPC plugin system
  • Auth profile rotation — multiple API keys or OAuth tokens per provider, with automatic round-robin and cooldown on rate limits
  • Two-stage failover — first rotate credentials within a provider, then fall back to the next model in the chain. Exponential backoff on failures.

Getting started? See the Configuration Guide for step-by-step setup instructions. For the full architecture, see docs/design/providers.md.

Scheduler

OpenTalon includes a built-in scheduler for periodic background jobs. Jobs can be defined statically in config.yaml or created dynamically through conversation — the LLM proposes a schedule, the user confirms, and the job is persisted.

flowchart LR
    Scheduler["Scheduler (tick)"] --> Runner["Execute plugin action"]
    Runner --> Result["Result"]
    Result --> Notify["Notify channel (Slack, Teams, …)"]
    
    User["User via chat"] -->|"create / list / delete"| LLM
    LLM -->|"scheduler tool"| Scheduler
    Config["config.yaml"] -->|"static jobs"| Scheduler
Loading

Example: Monitor GitHub and notify Slack

scheduler:
  approvers: ["ops@company.com"]
  max_jobs_per_user: 5
  jobs:
    - name: github-status
      interval: 10m
      action: github.check_status
      args:
        org: "opentalon"
      notify_channel: slack-ops
    - name: deploy-digest
      interval: 24h
      action: github.deployment_summary
      args:
        repo: "opentalon/opentalon"
      notify_channel: slack-engineering

Every 10 minutes, the github plugin checks the organization's status and posts results to the slack-ops channel. A daily deployment digest goes to slack-engineering.

Dynamic jobs via conversation

Users can also create jobs by talking to the LLM:

User: "Watch the opentalon/opentalon repo for failed CI runs and let me know in #builds"

LLM: "I'll create a job that checks CI status every 20 minutes and notifies #builds. Should I go ahead?"

User: "Yes, but check every 15m"

LLM: "Done — created job ci-watch-opentalon running every 15m, notifying #builds."

Governance

  • Config-defined jobs are immutable — users cannot modify or remove them through conversation
  • Approvers — when configured, only designated users can create, update, or delete dynamic jobs
  • Per-user limitsmax_jobs_per_user prevents any single user from creating excessive jobs
  • Full CRUD — list, pause, resume, update, and delete jobs through the LLM or directly via the scheduler API

Pipeline Execution

When a user request involves multiple steps (e.g. "check the bug in AppSignal, create a Jira ticket, and open a merge request"), OpenTalon's pipeline planner decomposes it into a structured plan, asks for confirmation, and executes each step with built-in retry and error reporting.

flowchart LR
    User["User Message"] --> Planner["Planner (LLM)"]
    Planner -->|"multi-step"| Plan["Plan + Confirm"]
    Plan -->|"approved"| Executor["Pipeline Executor"]
    Executor --> Results["Results"]
    Planner -->|"single-step"| AgentLoop["Agent Loop"]
    AgentLoop --> Results
Loading

How it works

  1. Planner — a separate LLM call decomposes the user prompt into a DAG of steps with dependencies. If the prompt is a simple single-step request, the normal agent loop handles it (safe degradation).
  2. Confirmation — the plan is presented to the user via their channel (Slack, console, etc.). The user approves (y/yes) or rejects. Nothing executes without explicit approval.
  3. Executor — walks the step DAG in dependency order. Each step calls a plugin action via gRPC. Per-step retry with exponential backoff, per-step timeout, and fail-fast or continue-on-error behavior.
  4. Results — on completion (or failure), the user sees what succeeded, what failed, and how many retries were attempted. All tool calls and results are recorded in the session history.

Example conversation

User: "Check bug #4521 in AppSignal, then create a Jira ticket and open a GitLab MR with the fix"

OpenTalon:

I've created a plan with the following steps:

1. Check bug in AppSignal
   Action: appsignal.get_error (error_id=4521)
2. Create Jira bug ticket
   Action: jira.create_issue
   Depends on: 1
3. Create MR with fix
   Action: gitlab.create_mr
   Depends on: 1, 2

Proceed? (y)es / (n)o

User: "y"

OpenTalon: "Pipeline complete — 3/3 steps succeeded."

Configuration

orchestrator:
  pipeline:
    enabled: true          # default false
    max_step_retries: 3    # retries per step before giving up (default 3)
    step_timeout: "60s"    # per-step timeout as Go duration (default "60s")

Concurrency

By default, OpenTalon processes one session at a time (max_concurrent_sessions: 1). This matches the original sequential behaviour and is the safe default for most deployments. Enable concurrent session processing by raising the limit:

orchestrator:
  max_concurrent_sessions: 5   # up to 5 sessions run in parallel (default: 1)

How it works:

  • Different sessions run in parallel — up to the configured limit. Session A no longer waits for Session B to finish.
  • Same session is always serialized — a second message to the same session waits for the first to complete, regardless of the limit. This preserves conversation ordering.
  • Backpressure is built-in — when the limit is reached, new requests wait until a slot is free (or their context is cancelled).
max_concurrent_sessions: 3

Session A ──────────────────► reply A   ┐
Session B ──────────────────► reply B   ├─ run in parallel
Session C ──────────────────► reply C   ┘
Session D ···················► (waits for A, B, or C to finish)

Same session:
Session A msg1 ──────────────► reply 1
Session A msg2 ···············► (waits for msg1 to finish) ──► reply 2

Set max_concurrent_sessions to match your LLM provider's rate limits and expected load. A value of 1 (default) gives the original sequential behaviour with no behaviour change needed for existing deployments.

Debugging

Set LOG_LEVEL=debug to see pipeline decisions, planner LLM calls, step execution, and retry attempts — all prefixed with [pipeline].

When debug is enabled, each conversation also writes to its own log file under {data_dir}/logs/ (default ~/.opentalon/logs/). Files are named by timestamp and the first message, e.g. 20260318_093609_wazzup.log, so you can quickly find and read logs for a specific chat. Non-ASCII first messages (emoji, cyrillic) use a short hash instead. Override the directory with log.dir:

log:
  file: ~/.opentalon/opentalon.log   # global log file (all sessions)
  dir: ~/.opentalon/logs             # per-session log directory (optional, defaults to {data_dir}/logs)

Log files older than 7 days are cleaned up automatically on startup.

Current limitations (Phase 1)

  • In-memory only — pipeline state is not persisted; a process restart loses pending/running pipelines (persistence planned for Phase 4)
  • No step output templating — template references like {{steps.1.output.id}} are passed literally to plugins (planned for Phase 3)
  • Sequential execution only — steps with independent dependencies run one at a time (parallel execution planned for Phase 3)
  • LLM quality dependent — weaker models may return single-step plans for multi-step requests, causing fallback to the agent loop (expected safe degradation)
  • No recovery advisor — failed steps are retried as-is without LLM-assisted diagnosis (planned for Phase 2)

For the full roadmap (recovery advisor, replan, parallel execution, persistence), see docs/design/pipeline.md.

Build locally with plugins

Prerequisites: Go 1.24+, git.

Quick start (recommended)

git clone https://github.com/opentalon/opentalon.git
cd opentalon
cp config.example.yaml config.yaml
# Set your API key (DeepSeek, OpenAI, or any compatible provider):
export DEEPSEEK_API_KEY="your-key"

make build setup   # build core binary + clone & build hello-world plugin and console channel
./opentalon -config config.yaml

make setup clones opentalon/console-channel into channels/ and opentalon/hellow-world-plugin into plugins/, then builds both. The binaries land at channels/console-channel/console and plugins/hellow-world-plugin/hello-world-plugin — matching the paths in config.example.yaml.

Other useful Make targets:

Target What it does
make build Build the core binary
make setup Clone and build the hello-world plugin and console channel
make plugin Clone and build only the hello-world plugin
make channel Clone and build only the console channel
make run Build + setup + start OpenTalon
make test Run tests with race detector
make lint Run golangci-lint
make all deps + build + test + lint
make clean Remove built binaries

Alternative: GitHub auto-fetch (bundler)

Instead of building locally, you can let OpenTalon fetch and build plugins/channels on first run. In config.yaml, replace plugin: with github: and ref::

channels:
  console:
    enabled: true
    github: "opentalon/console-channel"
    ref: "master"
    config: {}

plugins:
  hello-world:
    enabled: true
    github: "opentalon/hellow-world-plugin"
    ref: "master"
    config: {}

The first run resolves the refs, clones and builds, and writes channels.lock and plugins.lock under state.data_dir (default ~/.opentalon). Later runs reuse the locked versions until you change ref or delete the lock entries.

Reusable skills from OpenClaw

You can add request packages — skill-style API calls with no compiled plugin. The core runs HTTP requests from templates ({{env.VAR}}, {{args.param}}), with optional guardrails (required_env). This is a good fit for OpenClaw/ClawHub-style skills: each skill is a directory with a SKILL.md (and optionally request.yaml), and OpenTalon can download skills by name so you only specify the skill name in config.

Download skills by name — set a default repo and list the skill names you want. The core clones the repo once (or one repo per skill if you override), parses each skill’s SKILL.md, and registers them as tools. No build step.

request_packages:
  default_skill_github: openclaw/skills    # one repo, many skill subdirs
  default_skill_ref: main
  skills:
    - jira-create-issue
    - slack-send

For a skill from a different repo, use the object form:

request_packages:
  skills:
    - name: my-custom-skill
      github: myorg/my-skills
      ref: v1

Downloaded skills are stored under state.data_dir and pinned in skills.lock (same idea as plugins.lock). You can also use a local directory of skills with skills_path, or define inline request packages in config — see config.example.yaml for the full request_packages options.

Contributing

We welcome contributions of all kinds — bug reports, feature requests, documentation improvements, and code.

  1. Report issues — found a bug or have an idea? Open an issue with a clear description and steps to reproduce
  2. Submit pull requests — fork the repo, create a feature branch, and open a PR against master. Keep PRs focused on a single change
  3. Write tests — every PR must include tests. The CI pipeline runs go test -race ./... and golangci-lint — both must pass before merging
  4. Follow conventions — idiomatic Go, gofmt-formatted, meaningful commit messages. Read the existing code to match the style
  5. Discuss first — for large changes or new features, open an issue to discuss the approach before writing code

All contributions are subject to the Apache 2.0 License.

License

OpenTalon is licensed under the Apache License 2.0.