Skip to main content

🔁 OpenLoop

The open-source control plane & runtime for team AI agents

Persistent, asynchronous teammates that work across your channels — Slack, Discord, Zoom, GitHub, Linear — each with their own memory, tools, model policy, budget, approval rules, and audit trail.


CI PyPI Python License Model-agnostic PRs welcome Status: early/WIP


Why · vs. Claude Tag · Features · How it works · Quickstart · Capabilities · Contributing

Status: early / WIP. Not production-ready. APIs, config formats, and the commands below will change. Commands marked (preliminary) are placeholders.

Why

Most AI assistants are personal and single-player. Real work happens across shared channels, threads, calls, repos, and issues — and it spans more than one tool. The useful primitive isn't "a Slack bot" — it's a persistent team teammate that remembers your team's decisions, uses a scoped set of tools, routes tasks to the right model, stays in budget, asks before doing anything risky, and leaves an audit trail.

OpenLoop gives your team such an agent, reachable across the surfaces you already use, with an open-source runtime you can self-host and inspect. Slack/Discord/Zoom/GitHub/Linear are surfaces — the product is the agent runtime and control plane behind them. Memory, tools, and policy can be scoped per channel so context doesn't leak across teams.

For: engineering, data, and platform teams; AI-heavy startups; OSS maintainers; anyone who wants Claude Tag–style workflows without single-vendor lock-in.

How this differs from Claude Tag

Comparison based on Anthropic's Claude Tag announcement (June 2026). Claude Tag is evolving quickly — check the source for current details.

OpenLoop shares Claude Tag's core model — persistent, asynchronous, multiplayer team agents with tools and memory — and extends it in a model-agnostic, configurable, multi-surface, open-source direction. The first rows below are common ground; the rest are where OpenLoop goes further.

Dimension Claude Tag OpenLoop
Persistent Long-lived agent that stays active and retains team context Long-lived agent that stays active and retains team context
Asynchronous Event- and mention-driven; works in the background, replies when ready Event- and mention-driven; works in the background, replies when ready
Multiplayer Shared in team channels, not a personal assistant Shared across team surfaces, not a personal assistant
Team context Channel-level Claude identities with scoped memories and shared conversations Configurable memory scope across channel, agent, or workspace
Tools Admin-approved tool access inside Claude's managed product Explicit MCP/native tool allowlists, approval gates, and auditable actions
Models Claude-native / Anthropic-first Model-agnostic routing across Anthropic, OpenAI, Gemini, Ollama, OpenRouter, or any LiteLLM-compatible provider
Configuration Admin-managed product settings Config-as-code agents for surfaces, memory, model policy, tools, approvals, and budgets
Surfaces Slack first, with other workplace integrations planned Designed as a surface-agnostic runtime for Slack, Discord, GitHub, Linear, Zoom, and more
Deployment Managed Anthropic experience Self-hostable, inspectable, open-source infrastructure
Best for Teams that want a managed Claude-centered teammate Teams that want multiplayer agents with provider choice, deeper policy control, and open infrastructure

What it does (MVP)

  • Summarize Slack/Discord threads and remember team decisions
  • Create GitHub issues from discussions
  • Investigate failing CI/builds
  • Draft PRs via a coding worker, gated on human approval
  • Track token/cost usage per channel, agent, task, and model
  • Route tasks across providers (OpenAI, Anthropic, Gemini, Ollama, OpenRouter, any LiteLLM-compatible) — not only Claude
  • Require human approval before risky write actions

Concepts

Concept Meaning
Workspace Top-level tenant; owns agents, integrations, policy defaults.
Agent A team agent reachable across surfaces — the unit of identity, memory, and policy.
Surface Where you reach the agent: Slack, Discord, Zoom, GitHub, Linear.
Memory Scope What an agent recalls; can be scoped per channel so context doesn't leak across teams.
Tool Policy Explicit allowlist of tools (MCP / native) and their permissions.
Model Policy Which model handles which kind of task.
Human Approval Gates requiring a human before write/risky actions.
Budget Per-agent (optionally per-channel) spend and token limits, tracked and enforced.

How it works

flowchart TB
    subgraph SURFACES["🗣️ &nbsp;Surfaces &nbsp;<sub>(shared team channels)</sub>"]
        direction LR
        S1[Slack] ~~~ S2[Discord] ~~~ S3[Zoom] ~~~ S4[GitHub] ~~~ S5[Linear]
    end

    subgraph SELF["🏠 &nbsp;Self-hosted — your infra, your keys, inspectable"]
        RT["⚙️ &nbsp;Agent Runtime<br/><sub>shared team agent · loads policy · budget</sub>"]
        MG["🧠 &nbsp;Model Gateway<br/><sub>LiteLLM · model-agnostic</sub>"]
        TG["🔧 &nbsp;Tool Gateway<br/><sub>MCP + native · allowlist</sub>"]
        DB[("🗄️ &nbsp;Postgres + pgvector<br/><sub>channel-scoped memory · budget · audit</sub>")]
        HA{{"✋ &nbsp;Human approval"}}
    end

    subgraph MODELS["☁️ &nbsp;Model providers <sub>(external)</sub>"]
        direction TB
        M1[OpenAI] ~~~ M2[Anthropic] ~~~ M3[Gemini] ~~~ M4[Ollama] ~~~ M5[OpenRouter]
    end

    subgraph TOOLS["🛠️ &nbsp;Tool targets <sub>(external)</sub>"]
        direction LR
        T1[GitHub] ~~~ T2[CI] ~~~ T3[Coding worker]
    end

    SURFACES -- "mention / event" --> RT
    RT -- "model policy" --> MG
    RT -- "tool policy" --> TG
    RT <-. "read / write" .-> DB
    MG -- "your provider keys" --> MODELS
    TG -- "reads" --> TOOLS
    TG -- "write actions" --> HA
    HA -- "approved" --> TOOLS

    classDef runtime fill:#7c3aed,stroke:#5b21b6,color:#fff,font-weight:bold
    classDef gateway fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
    classDef store fill:#0ea5e9,stroke:#0369a1,color:#fff
    classDef gate fill:#f59e0b,stroke:#b45309,color:#1f2937,font-weight:bold
    class RT runtime
    class MG,TG gateway
    class DB store
    class HA gate
    style SELF fill:#faf5ff,stroke:#7c3aed,stroke-width:2px,stroke-dasharray:7 4

A mention or event on any surface triggers the team's agent. The runtime loads its memory, tool policy, model policy, and budget; routes the task to a model; uses only allowed tools; pauses for approval on write actions; then records usage, cost, and outcome to the audit trail and memory.

Example: Slack

#dev-platform

@maciag.artur @openloop summarize this thread and capture the decision

@openloop 📝 Summary (last 24 messages):
          • Moving ingestion off the legacy queue.
          • Redis Streams chosen over Kafka for v1 (lower ops overhead).
          • Owner: @maciag.artur, target: end of next sprint.

          🧠 Saved to channel memory: "Use Redis Streams for ingestion v1. Owner: @maciag.artur."
          Open a GitHub issue to track it?

@maciag.artur yes

@openloop ⏳ Write action (create issue in openloop-team/openloop) — approval required.
          @maciag.artur, approve?   💸 est. $0.02 · claude-sonnet-4-6

Example: agent config

Agents are config-as-code (apiVersion v1alpha1, preliminary). Full example: agents/dev-platform.yaml.

apiVersion: openloop.team/v1alpha1
kind: Agent
metadata: { name: dev-platform, workspace: acme }
spec:
  surfaces:
    - { type: slack, channel: "#dev-platform" }
    - { type: discord, channel: "eng" }
  memory: { scope: channel, backend: postgres, retention_days: 90 }
  model_policy:
    default: anthropic/claude-sonnet-4-6
    routes:
      - { match: { task: summarize }, model: openai/gpt-4o-mini }
  tools:
    - { name: github, type: native, permissions: ["issues:write", "pulls:read"] }
  approvals:
    require_for: ["github.issues:write", "github.pulls:write"]
    approvers: ["@maciag.artur", "@maintainers"]
  budget: { monthly_usd: 50, per_task_usd: 0.50, on_exceeded: block }
  limits: { max_concurrent_tasks: 4, tasks_per_minute: 30 }

Architecture

Layer Now Later
API / backend FastAPI —
Agent runtime durable workflow engine (worker + chat pipeline as workflows) model-call replay/caching semantics; retry policies
Model gateway LiteLLM routing analytics
Tools MCP gateway + native GitHub/Slack more native connectors
Storage Postgres + pgvector —
Queue Redis —
Surfaces Slack Discord / Zoom / GitHub / Linear
Delivery persisted Slack sessions, background progress/final postbacks, approval + thread-reply continuation, startup reconciler provider idempotency keys, cross-process delivery locks, more surface adapters
Coding worker draft PRs (credential-free worker edits a prepared workspace; the orchestrating boundary owns clone/commit/push) OpenHands-style
Dashboard — Next.js
Observability — OpenTelemetry / Langfuse traces

The open-source runtime covers: agent runtime, Slack integration with async delivery, model adapters (LiteLLM), MCP tool gateway, local Postgres channel/thread memory, approval flow, basic token/cost tracking, Docker Compose deploy, and config-as-code agents.

Quickstart (preliminary — commands are placeholders)

Requires Docker + Compose and at least one model provider key.

git clone https://github.com/p1c2u/openloop.git
cd openloop
cp .env.example .env                  # non-secret Compose values
# Configure the openloop-deploy, openloop-runtime, and openloop-broker
# Doppler projects, then inject their secrets into Compose:
mise run secrets-invoke -- mise run compose-up-d
openloop agents apply -f agents/dev-platform.yaml
# invite the bot to a channel, then: @agent summarize this thread

Nothing leaves your machine except calls to the providers/tools you configure.

External OpenHands broker

The external-broker composition keeps Docker authority out of the application runtime. A digest-pinned, networkless HAProxy container is the only service that mounts the raw Docker socket. It forwards the unfiltered Docker API to a private named-volume UDS owned by root:${OPENLOOP_DATA_GID:-10777} with mode 0660; the non-root broker keeps that data group and mounts the volume read-only. The adapter is a permission shim, not an API policy boundary—access to its forwarded socket remains root-equivalent Docker access.

cp .env.example .env
# Set an absolute OPENLOOP_BROKER_ROOT in .env.
# Edit tracked non-secret settings under configs/prd/.
mise run compose-build
mise run secrets-invoke -- mise run compose-up

Compose loads configs/prd/runtime.env and configs/prd/broker.env through service-level env_file. These tracked files contain only ordinary settings and public verification keys. Doppler injects true secrets into the Compose process, and Compose creates the declared /run/secrets/* files without writing a plaintext secret inventory into the repository.

DOCKER_SOCKET may select a non-default upstream Unix socket. Do not configure DOCKER_GID or a TCP Docker endpoint. The adapter healthcheck uses a separate root-only UDS and blocks broker startup unless HAProxy's checked /_ping backend is available. Under its read-only root filesystem, only the forwarded socket volume, private health tmpfs, and mounted upstream socket are writable.

Mounted secrets

Each top-level Compose secret names an environment value supplied by the appropriate Doppler project. Compose materializes it as /run/secrets/<lowercase-settings-field> and grants it only to the services that declare it. OpenLoop type-validates file contents like environment values, including JSON root maps. The GitHub App PEM is available at /run/secrets/github_app_private_key.

The grants are:

  • Postgres receives only postgres_password.
  • Runtime receives the database password, application credentials, and app-side broker secrets.
  • Broker receives the database password and broker-owned root maps.

See ops/compose-secrets.md for the complete inventory.

Local development (preliminary)

The runtime is a Python/FastAPI app. Local dev uses mise to pin the toolchain and manage a project virtualenv — no global installs.

mise install                 # Python 3.12 + uv + an auto-created .venv
mise run install             # install the runtime + dev deps (uv) into .venv
mise run test                # run the test suite
mise run dev                 # FastAPI runtime with autoreload on :8000
mise run apply -- -f agents/dev-platform.yaml   # validate an agent config

Try it against real Slack (Socket Mode)

Socket Mode opens an outbound WebSocket, so you can test a real mention → reply → approval round-trip locally — no public URL or tunnel. Set up a Slack app once, then run the socket:

  1. Enable Socket Mode and generate an app-level token with the connections:write scope → this is your SLACK_APP_TOKEN (xapp-…).
  2. Add bot OAuth scopes (OAuth & Permissions → Bot Token Scopes): chat:write, app_mentions:read, channels:history, and files:write (long answers, diffs, and logs use hosted snippets). For private channels and DMs, also add groups:history, im:history, mpim:history.
  3. Subscribe to bot events (Event Subscriptions → Subscribe to bot events) — Slack only delivers events you subscribe to:
    • app_mention — direct @bot mentions.
    • message.channels — lets the bot follow up on replies in a thread it already owns without being re-mentioned.
    • message.groups / message.im / message.mpim — the same for private channels and DMs.
  4. Install the app to your workspace, copy the bot token → SLACK_BOT_TOKEN (xoxb-…), and invite the bot to a channel.
  5. Set the runtime secrets: add a model key, SLACK_BOT_TOKEN, and SLACK_APP_TOKEN to the openloop-runtime Doppler project. Then run:
doppler run --project openloop-runtime --config dev_personal -- \
  mise exec -- openloop slack socket   # connects; mention the bot in a channel

Mention the bot to start a thread; you can keep replying in that thread without re-tagging it. Read-only observability while it runs: GET /usage (spend vs. budget) and GET /audit (recent token/cost records).

End-to-end tests

The E2E suite is layered so each slower or less deterministic dependency is isolated.

A. Unit and integration tests: isolated logic tests plus in-process runtime, memory, usage, tool gateway, approval, Slack, MCP, and HTTP API tests. External providers, GitHub, and Postgres are faked, so this runs without credentials, Docker, or network:

mise run test
mise run test-unit          # optional: only tests/unit
mise run test-integration   # optional: only tests/integration

B. Postgres E2E: real Postgres/pgvector stores, fake model and fake GitHub. This validates SQL, asyncpg type handling, vector recall, approval persistence, and usage persistence:

mise run test-e2e

C. Runtime/GitHub live E2E: real model, approval gate, and real GitHub issue creation. It creates and then closes one issue, so it is explicitly opt-in:

export E2E_CONFIRM=1
export E2E_MODEL=groq/llama-3.3-70b-versatile
export GROQ_API_KEY=gsk_…             # or set another LiteLLM provider key
export GITHUB_TOKEN=github_pat_…       # issues:write on the repo
export E2E_GITHUB_REPO=you/sandbox
export DATABASE_URL=postgresql://openloop:change-me@localhost:5432/openloop  # optional
mise run test-e2e-runtime-github-live

You can also invoke the live pytest target directly:

E2E_LIVE=1 GITHUB_TOKEN=… E2E_GITHUB_REPO=you/sandbox \
  E2E_MODEL=groq/llama-3.3-70b-versatile GROQ_API_KEY=gsk_… \
  mise exec -- python -m pytest tests/e2e/test_runtime_github_live.py -v

GitHub Actions runs unit and integration tests on pull requests and pushes to main. The runtime/GitHub live E2E workflow is separate, runs nightly or manually, and uses a protected live-e2e environment. Configure repository secrets GROQ_API_KEY and LIVE_E2E_GITHUB_TOKEN; the latter should be a fine-grained token with issue write access to openloop/openloop-e2e-sandbox.

D. Interactive Slack smoke (a human in the loop). With SLACK_BOT_TOKEN + SLACK_APP_TOKEN set, run openloop slack socket, mention the bot in a channel, and click Approve on a held write action.

E. Automated Slack live E2E: real Socket Mode round-trip with a stubbed model, so it proves the Slack wire (auth, event delivery, in-thread reply) without LLM nondeterminism. The triggering mention is posted with a user token, not the bot token — Slack suppresses app_mention for messages an app posts as itself, so a bot mentioning itself never fires the event. Add the user-token scope chat:write (OAuth & Permissions → User Token Scopes) and reinstall to get an xoxp-… token:

cp .env.e2e.example .env.e2e
# Set E2E_SLACK_USER_TOKEN and E2E_SLACK_CHANNEL in .env.e2e.
export E2E_CONFIRM=1
mise run secrets-invoke -- mise run test-e2e-slack-live

The Slack live E2E GitHub Actions workflow is manual-only and uses a protected slack-live-e2e environment. Configure environment secrets SLACK_BOT_TOKEN, SLACK_APP_TOKEN, and E2E_SLACK_USER_TOKEN; set E2E_SLACK_CHANNEL as an environment/repository variable, or pass a channel ID when manually dispatching the workflow.

Current capabilities

  • Core async runtime + task pipeline
  • Slack surface (mentions, thread replies, approvals)
  • LiteLLM gateway + model-policy routing
  • MCP tool gateway + native GitHub connector
  • Channel/thread memory (Postgres + pgvector)
  • Human approval flow + token/cost tracking
  • Docker Compose + config-as-code
  • Coding worker (draft PRs) — connector + approval gate + crash-resumable; hardened (Phase 2): the worker is credential-free (edits a prepared workspace), all credential-bearing git ops live in one orchestrating boundary shared by both durable paths, and git auth rides a per-command header (never a token-in-URL clone, nothing in the workspace)
  • Worker sandbox (Phase 3) — model-generated edits can run in a throwaway docker container: default-deny egress (network none), no env forwarded (LLM key stays in the controller), capabilities dropped, auto-reaped; fail-closed wiring (an unusable sandbox disables the worker, never silently runs on the host). CODING_WORKER_SANDBOX=docker
  • OpenHands worker backend + spend ledger (Phase 4) — pluggable worker backends behind CODING_WORKER_BACKEND=builtin|openhands: the default stays the light diff worker; openhands drives an agentic OpenHands run over the same prepared, credential-free workspace (openhands dependency group; with CODING_WORKER_SANDBOX=docker the agent server runs containerized with the workspace bind-mounted — the container never holds a git credential, the host pushes). Every attempt's model spend is recorded to the usage store and capped fail-closed by the owning agent's per_task_usd before anything is pushed — on both durable paths — and the agentic backend refuses to register without that cap
  • OpenHands cold resume — the Docker agent-server is digest-pinned, loopback-only, and authenticated; conversation state lives in a private per-job mount outside the checkout; independent per-job keys protect conversation state and AES-GCM workspace artifacts. Confirmation boundaries park without staging or pushing, settle cumulative spend once per segment, discard the container, and expose explicit Slack Accept/Reject actions. Resume reconstructs a fresh checkout from the recorded base SHA and authenticated delta, attaches without resending the prompt, and retains a final artifact until the draft PR is durable. Enabled by default for Docker OpenHands; set CODING_WORKER_OPENHANDS_COLD_RESUME_ENABLED=false as an operational rollback.
  • Claude Code worker backend (CODING_WORKER_BACKEND=claude) — experimental, personal use only: drives the claude CLI in headless mode (claude -p) over the same prepared, credential-free workspace, authenticating with whatever claude is logged into — including a Pro/Max subscription. Because the subscription dollar signal is unreliable (total_cost_usd is an API-equivalent estimate, often 0), the load-bearing fail-closed bound is resource-based — --max-turns and a hard wall-clock deadline (the subprocess is killed on expiry) — while the spend ledger still records the estimate and enforces per_task_usd when it is non-zero. Host sandbox only (docker isolation for this backend is not implemented; requesting it fails closed). ⚠️ Anthropic designs the subscription for individual use through its first-party apps, not for powering a shared team runtime — pooling one subscription across a team surface is outside that intent and may violate the Consumer Terms. Availability rides on a private CLI/auth contract that can change between claude releases. Keep it off by default; for anything shared or production use metered API keys (builtin/openhands) or a local model. The backend seam makes reverting one env var
  • Budget/usage unification + throughput limits (Phase 5) — worker spend is attributed to the invoking agent (threaded through the approval args, so multi-agent configs charge and cap the right budget) and gated by that agent's monthly budget before an attempt does any work (block | warn preserved); per-agent rate/concurrency limits (spec.limits: max_concurrent_tasks, tasks_per_minute) refuse excess tasks at the runtime entry with a tenant-shaped scope key, recorded in the audit trail
  • Durable workflows — engine + approval-as-wait-node; worker resumes on crash; chat pipeline runs as a workflow (bounded: persisted turn state + idempotent writes; model calls are not replayed on crash)
  • Slack async delivery — persisted surface sessions, thinking status + final postbacks, approval/thread-reply continuation, startup reconciler, conversation-history threading (a follow-up turn replays the thread's prior exchanges), idempotency-keyed delivery (a crash between a successful post and recording its id is recovered by key instead of re-posting; best-effort, falls back to at-least-once if the surface lookup can't run), and delivery outside the original request lifecycle
  • Cross-process coordination — a distributed lock so that when several replicas boot together only one leads recovery, re-run on an interval so a leader that dies mid-sweep is healed by a survivor. LOCK_BACKEND=auto (default) uses Postgres advisory locks when the deploy already runs Postgres — no extra service — with Redis and process-local backends also available

Scope

This repository is the open-source runtime and control plane — self-hosted, inspectable, and the whole product for now.

It covers the agent runtime, model gateway (LiteLLM), MCP tool gateway + native connectors, channel/thread memory, approval flow, token/cost tracking, Slack async delivery, config-as-code, and Docker Compose deployment.

Security

Agents act on your behalf — treat their credentials like a production service account.

  • Least privilege: give each agent the narrowest tool scope it needs; never broad org-wide credentials.
  • Approve writes: require human approval for creating issues/PRs, posting externally, or deleting anything.
  • Scoped tokens: use fine-grained, per-integration tokens.
  • Memory isolation: scope memory per channel so context doesn't leak.
  • Secrets: keep real values in the three scoped Doppler projects. Compose creates the declared /run/secrets/* files from injected values; tracked configs/prd/*.env files must contain only non-secret settings and public verification material.
  • Inspect: self-host the runtime to see exactly what the agent does.

Early-stage software, no warranty. Don't connect sensitive production systems until you've reviewed the threat model for your environment.

Contributing

Early project — shaping the foundations is the most valuable work. Open an issue before anything non-trivial. Help wanted on the runtime, model adapters, MCP connectors, Slack surface, memory layer, and docs. See CONTRIBUTING.md.

License

Apache-2.0.

Metadata

Release files for pyopenloop 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyopenloop 0.1.1
File Size Uploaded
pyopenloop-0.1.1.tar.gz 1.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyopenloop 0.1.1
File Interpreter ABI Platform
pyopenloop-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.5 MB

Release files / pyopenloop-0.1.1.tar.gz

Download URL pyopenloop-0.1.1.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
3f9ecf127c9d2136e649c4426bf7bc7010410630f68cca7d635d7d5c476b5967
BLAKE2b-256 checksum
How to use checksums
a88f4fdf4fc1a20a96bacee756e0a5161452c9af5f8134ea9e51b2750e651502
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release files / pyopenloop-0.1.1-py3-none-any.whl

Download URL pyopenloop-0.1.1-py3-none-any.whl
Size 412.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
036d92f4b555636f0edcad609224fca26d042a5bdf6634bea10100e3326b41f9
BLAKE2b-256 checksum
How to use checksums
5d87b2b8bf9c008008d5b4a3b6738c921706e97d5d131b1f5bc856d950512b9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page