opentag

module
v0.0.0-...-f77c845 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: Apache-2.0

README

opentag

Tag an agent from anywhere. Stream it to everyone. Deliver it anywhere.

Download · Report Bug · Go Docs

  CI   Go Reference   License

Status

opentag is beta software. It is pre-1.0 and not yet recommended for production.

Interfaces are stabilizing but may change between minor versions, and a minor release may require code changes on your side.

What that means concretely today:

  • Works and is tested. The single-binary deployment (in-memory bus, ledger and registry), the topic and delivery model, durable runs with replay, the Connect and SSE transports, and the Slack, GitHub, Jira, cron and webhook connectors.
  • Written but not exercised in CI. The Redis Streams bus backend passes the shared conformance suite, but its integration tests skip without a Redis to point at.
  • Not built yet. A persistent registry: agent specs live in memory, so they do not survive a restart.

See Limitations for the full list.

opentag is an agent platform and a low-latency pub/sub bus. Define an agent with a spec, tag it from Slack, GitHub, Jira or a schedule, and its events stream to any subscriber while being delivered to any destination you name.

The idea it turns on: where a tag is raised and where its answer lands are independent. A review request raised in GitHub can answer into Jira. A nightly schedule nobody watched can answer into both. That is what makes it a mesh rather than a pile of integrations.

Features

  • Agents are documents. Create one by submitting a spec. No redeploy, no code, no restart.
  • Listen to an agent. One topic namespace, matched by prefix: agent:docs-bot receives every run of that agent, including runs that start after you subscribe.
  • Origin and destination are independent. Any trigger can raise a tag; any sink can receive it. They never call each other, they only publish and subscribe.
  • N:M delivery with per-route selectivity. One run streams every delta into a GitHub comment it keeps editing while a webhook on the same run receives only lifecycle.completed.
  • Connectors act, not just talk. The Actor face contributes native verbs (transition a Jira ticket, request a review) as agent tools, sandboxed by NGAC, each emitting an auditable action.taken event.
  • Durable by construction. Runs survive crashes and replay from a ledger. A redelivered webhook joins the run it duplicated instead of answering twice.
  • Revisions are pinned per run. A run accepted under revision 6 executes as revision 6 forever, even after a revise, because replay demands it.
  • Citations are first-class events, carrying the exact quoted source and resolvable provenance.
  • One contract, three transports. Connect serves gRPC, gRPC-Web and HTTP/JSON, plus resumable SSE for browsers.

Installation

Script (macOS / Linux)

curl -fsSL https://raw.githubusercontent.com/urmzd/opentag/main/install.sh | sh

Go

go install github.com/urmzd/opentag/cmd/opentag@latest

Library

go get github.com/urmzd/opentag

Quick Start

See the whole architecture run in one process, with no API key, no network and no infrastructure:

go run ./examples/local

It creates an agent, revises it, tags it from a simulated GitHub trigger with delivery routed to Slack and a webhook, shows a third party listening to the agent's topic, and demonstrates that a replayed run does not pay for the model twice.

Or run the real thing:

opentag serve &

cat > docs-bot.json <<'JSON'
{
  "name": "docs-bot",
  "description": "Answers questions about the deploy pipeline",
  "provider": "anthropic",
  "model": "claude-sonnet-5",
  "system_prompt": "You answer questions about the deploy pipeline. Cite your sources."
}
JSON

opentag agent create -f docs-bot.json
opentag tag docs-bot "how does a release get out the door?"

Deliver the answer somewhere other than your terminal, with each destination choosing its own granularity:

opentag tag review-bot "review this change" \
  --deliver 'github://urmzd/opentag/issues/42|delta' \
  --deliver 'webhook://acme/deploys|lifecycle.completed'

Watch the bus. This subscriber invoked nothing and still sees every run:

opentag listen agent:docs-bot
opentag listen agent --kinds lifecycle.completed --format json | jq

Commands

Command Purpose
opentag serve Run the core: API, SSE, webhooks, bus, router, worker
opentag work Run an execution node with no inbound API
opentag agent Create, revise, get, list, history, delete
opentag tag Tag an agent and stream its answer
opentag listen Subscribe to a topic and print events
opentag version Version, commit, build date
opentag update Self-update from GitHub releases

Every command takes --format text|json. Results go to stdout, diagnostics to stderr, so --format json output pipes cleanly into jq even while the same process logs a reconnect.

Documentation

Document Covers
docs/architecture/overview.md Topics, connector faces, N:M delivery, revision pinning, package DAG, limitations
AGENTS.md AI-facing conventions, commands, rules, extension guide
examples/README.md Runnable example index
CONTRIBUTING.md Development workflow and commit convention
SECURITY.md Security boundaries and reporting

API reference: pkg.go.dev/github.com/urmzd/opentag

How it composes

opentag builds on three libraries and adds addressing, distribution and the control plane:

Concern Owner
Agent loop, typed deltas, RAG, citations saige
Durability, replay, per-run journal duraturo
Sandboxed execution nodes, NGAC dispatch
Topics, bus, routing, connectors, specs opentag

Limitations

  • The bus requires Redis or the in-memory backend. duraturo's pgqueue does not implement DeltaLog, so a Postgres-only deployment runs durably but cannot stream.
  • The registry is in-memory only; a Postgres implementation is not written yet.
  • dispatch's queue is at-most-once in beta, so durability comes from duraturo rather than from dispatch.
  • Citations are derived from RAG context blocks, because saige v0.14.0 has no agent-level citation delta.
  • The bus is at-least-once with no consumer groups. If durable competing consumers become a requirement, NATS JetStream behind the Bus interface is a better answer than growing a broker here.
  • Agent specs load from JSON, not YAML.

License

Apache 2.0. See LICENSE.

Directories

Path Synopsis
cmd
opentag command
Command opentag is the agent platform and its pub/sub bus.
Command opentag is the agent platform and its pub/sub bus.
examples
local command
Command local is opentag, end to end, in one process.
Command local is opentag, end to end, in one process.
gen
internal
cli
Package cli is the opentag command tree and the process's composition root.
Package cli is the opentag command tree and the process's composition root.
server
Package server is opentag's transport edge.
Package server is opentag's transport edge.
pkg
address
Package address is the naming layer of the mesh: a stable URI for any place a tag can come from or be delivered to.
Package address is the naming layer of the mesh: a stable URI for any place a tag can come from or be delivered to.
agentrt
Package agentrt builds a running agent from a pinned agent revision.
Package agentrt builds a running agent from a pinned agent revision.
agentrt/payload
Package payload is the body of every event an agent run publishes.
Package payload is the body of every event an agent run publishes.
agentspec
Package agentspec is the canonical definition of an agent, and the rules that decide when two definitions are the same one.
Package agentspec is the canonical definition of an agent, and the rules that decide when two definitions are the same one.
bus
Package bus is the broker: a run publishes its events once, and every consumer that asked for them receives them.
Package bus is the broker: a run publishes its events once, and every consumer that asked for them receives them.
bus/bustest
Package bustest is the conformance suite every bus backend must pass.
Package bustest is the conformance suite every bus backend must pass.
connector
Package connector defines what it means to participate in the mesh.
Package connector defines what it means to participate in the mesh.
connectors
Package connectors holds the mesh: the concrete peers that raise tags and render events onto real surfaces.
Package connectors holds the mesh: the concrete peers that raise tags and render events onto real surfaces.
connectors/cron
Package cron is the schedule peer in the mesh: a trigger, and only a trigger.
Package cron is the schedule peer in the mesh: a trigger, and only a trigger.
connectors/github
Package github is the GitHub peer in the mesh: trigger, sink and actor.
Package github is the GitHub peer in the mesh: trigger, sink and actor.
connectors/internal/httpjson
Package httpjson is the JSON-over-HTTP client the connectors' real API implementations share.
Package httpjson is the JSON-over-HTTP client the connectors' real API implementations share.
connectors/internal/inbound
Package inbound is the front door every webhook trigger shares: authenticate the request, then hand the raw bytes to whoever knows how to read them.
Package inbound is the front door every webhook trigger shares: authenticate the request, then hand the raw bytes to whoever knows how to read them.
connectors/internal/render
Package render accumulates one run's event stream into a document a sink can draw, repeatedly, without ever drawing something stale.
Package render accumulates one run's event stream into a document a sink can draw, repeatedly, without ever drawing something stale.
connectors/internal/sink
Package sink is the delivery engine every human-facing connector shares: one message per run, edited as the run proceeds.
Package sink is the delivery engine every human-facing connector shares: one message per run, edited as the run proceeds.
connectors/jira
Package jira is the Jira peer in the mesh: trigger, sink and actor.
Package jira is the Jira peer in the mesh: trigger, sink and actor.
connectors/mention
Package mention finds the agent a human tagged and removes the mention from the text the agent will read.
Package mention finds the agent a human tagged and removes the mention from the text the agent will read.
connectors/slack
Package slack is the Slack peer in the mesh: trigger, sink and actor.
Package slack is the Slack peer in the mesh: trigger, sink and actor.
connectors/webhook
Package webhook is the outbound peer in the mesh: a sink, and only a sink.
Package webhook is the outbound peer in the mesh: a sink, and only a sink.
envelope
Package envelope is the contract every opentag client speaks, independent of transport.
Package envelope is the contract every opentag client speaks, independent of transport.
registry
Package registry is the agent control plane: the append-only record of what every agent has ever been, scoped by tenant.
Package registry is the agent control plane: the append-only record of what every agent has ever been, scoped by tenant.
router
Package router is the delivery half of the mesh: it turns "the agent said something" into "the surface shows it".
Package router is the delivery half of the mesh: it turns "the agent said something" into "the surface shows it".
runtime
Package runtime is the durable turn: where a tag becomes a run.
Package runtime is the durable turn: where a tag becomes a run.
signature
Package signature authenticates inbound webhook requests.
Package signature authenticates inbound webhook requests.
topic
Package topic is the addressing scheme of the opentag bus.
Package topic is the addressing scheme of the opentag bus.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL