v0.7.0 · pre-1.0

An AI teammate in Slack, under rules your admins write.

Libero runs one shared session per channel — not one per user. It holds no tool credentials, calls only the tools that channel’s team sheet allows, and stops for a human click before anything destructive. Self-hosted, MIT, model-agnostic.

What is current: the governed core, memory, skills — the channel's own and the operator's shared ones — ambient mode with operator-scheduled recurring turns, and sandboxed code execution, each attacked by the same test suite. It is what pilot deployments run from: three chosen ways to reach a model, managed secret stores beside the default encrypted files, tool results that carry an image as an image, and OAuth tokens bound to a key the token store does not hold. Pre-1.0 means the team-sheet format can still change between releases — the changelog says when it does, and which release is the current one.

The security property

Tool credentials live in the proxy. The agent reaches tools only through it.

Two processes. The gateway and agent talk to Slack and run the model loop. The tool proxy holds every tool credential and decides what each channel may do. They speak over mutual TLS on a private network, and the only thing that crosses is a tool call and its result.

That split is the whole design. Enforcement is a deterministic lookup against a file in your git repo — not a paragraph in a system prompt asking the model to behave.

How the two services fit together

gateway + agent service 1
slack adapter · socket mode
channel router · (team, channel) → session
agent loop · bring your own model
tool credentials none
tool proxy service 2
credential vault · encrypted at rest
team sheet · per-channel allowlist
approval broker · budget meter
audit writer · append-only
What the proxy enforces

Six things, none of which the model can talk its way past.

Credential vault

The agent process holds no tool credentials

Credentials are encrypted at rest in the proxy and referenced by name in team sheets, logs, and errors. The proxy injects them into the outbound call and scrubs known secret values out of the result before it crosses back. Compromise the agent — prompt injection, a bad skill, a misbehaving model — and you get none of them. The Slack tokens and the model key are in that process, because the gateway holds the socket; they reach nothing a team sheet governs.

Allowlist

Tools not on the sheet do not exist

Every call resolves against the channel’s team sheet in the proxy: is this server allowed here, is this tool listed, does this call need a human first. A refusal is a structured result the agent relays. The model’s cooperation is never part of the enforcement path.

Approvals

A human clicks before anything destructive

Tools marked approval = "required" are held in the proxy while an Approve once / Deny card renders in the thread. Approvals are per-call, recorded with the approver’s Slack user id, and expire in 15 minutes. Destructive verbs — delete, drop, transfer, deploy — default to required.

Budgets

Spend is metered where it cannot be argued with

Tokens and tool calls, per channel per day. The agent loop caps itself too, but the proxy’s meter is the authoritative one. A hard limit stops the loop until an admin resets it or the day rolls over, and a soft in-thread warning reaches the channel before it bites.

Audit

Every call, appended and never rewritten

Timestamp, channel, requesting user, task id, tool, server, argument hash, outcome, result size, and the approver if there was one. Append-only SQLite: triggers abort any UPDATE or DELETE, and an operator command queries and exports it.

Isolation

One database file per channel

Channel content — the history, the curated memory, and the skills a channel has written — gets a SQLite file scoped to that channel. The file-per-channel layout is the isolation boundary, so there is no schema or query that can join across channels by accident.

The admin surface

A TOML file per channel, in your own git repo.

We call it the channel’s team sheet — the sheet a manager submits before a match declaring who is allowed on the pitch, what position they play, and what needs the gaffer’s sign-off.

Nothing in it is a secret: credentials are names, resolved only inside the proxy’s vault. Changes are picked up on file change and validated against the schema; an invalid sheet is rejected loudly and the previous valid one stays active.

There is no web admin UI, and that is deliberate. The files in git are the admin UI — reviewable, diffable, revertable.

Team sheet reference

channels/C024BE91L/channel.toml valid
# Nothing here is a secret. Credentials are names,
# resolved only inside the proxy's vault.

[channel]
name = "engineering"
# Which client certificate may speak for this channel.
certificate_sha256 = ["B7:C6:75:…:38"]

[budget]
daily_tokens     = 2_000_000
daily_tool_calls = 400

[[mcp_server]]
name       = "github"
transport  = "http"
url        = "https://api.githubcopilot.com/mcp/x/pull_requests"
credential = "github_service_account"

  # Tools not listed here do not exist
  # as far as this channel is concerned.
  [[mcp_server.tool]]
  name     = "list_pull_requests"
  approval = "none"

  [[mcp_server.tool]]
  name     = "merge_pull_request"
  approval = "required"

[egress]
# Where sandboxed code may reach. No block, no network.
allow = ["api.github.com"]

[ambient]
enabled = false  # off by default, always
In the channel

Green ran. Amber is waiting on a person. Red never happened.

Colour means one thing here, and it is always status. Every row below is also a line in the audit log.

#engineering · task 4f2a 14:02
github.list_pull_requests executed
github.pull_request_read executed
github.merge_pull_request awaiting approval
github.delete_file not on allowlist
tokens · 41,220 of 2,000,000 today
Approval required expires in 15:00
github.merge_pull_request repo: getlibero/libero · pullNumber: 184 · merge_method: squash

Requested by @alice in #engineering. The team sheet marks this tool approval = "required", so the call is held in the proxy until someone approves it. Whoever clicks is recorded in the audit log.

Illustration — not a live agent.
Status

The governed core came before the features. Both are in.

The phases are gated on purpose. Nothing that depends on the proxy shipped before the proxy could be attacked and hold — and memory, skills, and ambient mode each landed with e2e attacks of their own. Every phase is shipped, and delivery is numbered now: one milestone per release, and a changelog an operator can upgrade by. v0.4.0 added code execution, governed the same way as every other tool; v0.5.0 added shared skills, published once by the operator and named per channel; v0.6.0 added scheduling — recurring turns at a clock time, authored in the team sheet the model cannot write; v0.7.0 added deployment shapes — three chosen ways to reach a model, and credential custody in Google Secret Manager or AWS Secrets Manager beside the default encrypted files; and v0.8.0 added richer tool results — an image crosses as an image — a per-channel persona, and sender-constrained OAuth tokens.

Definition of done, phase 1 — met

A prompt-injected agent in a test channel cannot exfiltrate a secret, call an unlisted tool, exceed budget, or act destructively without a human click — demonstrated by e2e tests that try, one file per property, run against every change.

PHASE 0
Skeleton done

Monorepo, schema package, design system, site, CI with the license gate and boundary checks, CLI placeholder on npm.

PHASE 1
The governed core done

Slack gateway, vault, team-sheet enforcement, approval cards, budget meter, audit log — and the e2e suite that attacks all of them.

PHASE 1.5
Consolidation done

Pool discipline against a hostile upstream, a bounded shutdown drain, budget caps in dollars, the CLI operators actually run, OAuth for MCP upstreams, deployment guides.

PHASE 2
Memory done

Curation inner loop, MEMORY.md tooling, semantic recall over thread summaries.

PHASE 3
Skills done

Author turn, retrieval-based loading, lifecycle job, merge proposals a person applies.

PHASE 4
Ambient done

Heartbeat evaluation, proactive posts behind a rate window, scheduled tasks — off by default, behind the budget meter.

PHASE 5
Hardening done

Proxy hardening pass, audit hash-chaining for tamper evidence, and an operator command that walks the chain.

Read the architecture before you decide.

It is the design of record, and since v0.4.0 it describes what runs. Where something landed differently from the plan, the roadmap says so.