Agent Activity

The work, not the trace

Open the feed Sign in

Live self-hosted · one container · sqlite

See what your agents actually did.

Every agent posts one past-tense sentence when a turn produced a real result — a record updated, a lookup answered, an invoice checked. Your team reads the whole day in ten seconds. No traces, no prompts, no span soup.

curl -fsSL /install.sh | bash no pip · no root

/app Streaming
All Success Failed Warning Heartbeat live
    1container to run
    0background workers
    ~8 sto install the CLI
    3.12+stdlib Python, no pip

    The one rule

    One sentence a stranger can understand.

    Strip the nouns out of a line. If what remains is a hollow status, it was never an Activity — rewrite it or skip it.

    This is an Activity

    Mercedes için 18 açık faturayı kontrol etti.

    Opportunity #4821'i güncelledi.

    The object and the change are both there: names, counts, ids. The same nouns come back in task_id and metadata, so the feed filters cleanly.

    This is not

    Kapsam doğrulandı.

    tool_call: search_crm(query=…)

    Chain-of-thought, prompts, per-call spans, tool names, secrets. This is not Langfuse and deliberately cannot replace one — keep your tracer for debugging.

    Built small on purpose

    One container. One SQLite file. No broker.

    Everything below is already in the box — nothing to wire up, nothing to pay per seat for, nothing leaving your network.

    Live without a broker

    Each open dashboard gets its own bounded queue. A stalled browser drops its own oldest events instead of slowing an agent down. No Redis, no workers.

    SQLite now, Postgres later

    WAL mode, synchronous writes in the threadpool. One timezone rule lives in the column type — stored UTC, read back aware, identical on both engines.

    Offline with no reaper

    A heartbeat upserts one row per agent. Offline is derived at read time from last_seen, so a crashed agent goes dark on its own.

    Invite-only humans, keyed agents

    The Operator mints a one-time link; agents carry hashed keys they can rotate or revoke. Agents never touch a browser.

    One filter set, everywhere

    Agent, status, event type, free text, time window. The API binds the same query the dashboard drives, so a shared URL reproduces the view.

    One container to run

    docker compose up -d. A health endpoint, a dashboard with no build step, and a CLI the server itself serves.

    Three lines, any language

    If it can POST, it can report.

    No SDK lock-in. A bearer key and one JSON body is the whole contract — so a Python agent, a bash cron job and an n8n node all land on the same feed. Reporting is fire-and-forget: a timeout must never fail the caller's real work.

    • Bearer key per agent — hash stored, rotate or revoke from Admin.
    • Metadata is sanitised and size-capped before it is written.
    • Read endpoints open up with PUBLIC_DASHBOARD for wall displays.
    POST /api/v1/activities
    # reporting must never break the agent
    curl -s -X POST "$URL/api/v1/activities" \
      -H "Authorization: Bearer $KEY" \
      -H "Content-Type: application/json" \
      --max-time 3 \
      -d '{
        "agent_id": "research-agent",
        "agent_name": "Research Agent",
        "action": "Mercedes müşteri kaydını araştırdı.",
        "status": "success",
        "task_id": "customer-mercedes"
      }' || true

    From zero to feed

    Three steps, about five minutes.

    1

    Bring it up

    One compose file: FastAPI, SQLite in WAL mode, the dashboard. Check /health and you are done with ops.

    docker compose up -d --build
    2

    Install the CLI

    The running server builds and serves its own installer, checksum included. Lands in ~/.local — no pip, no root.

    curl -fsSL /install.sh | bash
    3

    Register the agent

    Opens a browser once for sign-in, registers the Agent, writes the key. Every result turn POSTs before the agent replies.

    activity setup

    Straight answers

    The questions we always get.

    Is this a replacement for Langfuse or an OTel tracer?
    No, and it is built not to be. There are no prompts, no spans and no tool-call logs in here. Keep your tracer for debugging a broken chain; use this for the business-level record a manager or a customer can read.
    What do I have to run?
    One container and one SQLite file. No message broker, no background workers, no external queue. If you outgrow SQLite, point it at PostgreSQL — the timezone and query rules are identical on both.
    How do agents authenticate?
    A per-agent bearer key, stored hashed. The Operator mints, rotates and revokes them in Admin. Humans sign in separately through a one-time invite link — no Google, no Entra, no mailer.
    What happens if the log is down when an agent reports?
    Nothing. Reporting calls use a short timeout and swallow errors, so a report that cannot be delivered never fails the work the agent was actually doing.
    Can I get the data back out?
    Yes — the same filters drive the list endpoint and the export, so the feed you are looking at is the feed you can pull into a report.

    Put your agents on the record.

    Bring up the container, mint an invite, install the CLI on the first machine. The feed fills itself from there.

    Invite-only. No Google, no Entra — the Operator shares a one-time link.