Skip to content

Latest commit

 

History

History
292 lines (212 loc) · 27.5 KB

File metadata and controls

292 lines (212 loc) · 27.5 KB
Bernstein
Bernstein - the open-source governance layer for AI agents

"To achieve great things, two things are needed: a plan and not quite enough time." - attributed to Leonard Bernstein

otwartoźródłowa warstwa governance dla agentów AI

CI PyPI GHCR Python 3.12+ License OpenSSF Scorecard CodeQL Open in Codespaces MCP Toplist Ask DeepWiki

website · docs · install · first run · glossary · limitations · name policy · sponsor

简体中文 · 繁體中文 · 日本語 · 한국어 · हिन्दी · বাংলা · Русский · Español · Português · Deutsch · Français · Italiano · Nederlands · Polski · Svenska · Suomi · Українська · Türkçe · العربية · עברית · Bahasa Indonesia · Tiếng Việt · ไทย


Status: beta. Projekt rozwijany i utrzymywany przez jedną osobę. Numer wersji oznacza kolejne wydania, a nie dojrzałość — wersje minor mogą zmieniać interfejsy. Przypnij wersję dla istotnych zależności; regresje są naprawiane na bieżąco, zgłoś problem.

Bernstein to otwartoźródłowa warstwa governance dla agentów AI. Działa na policy as code: ty piszesz politykę - kto co może robić, co wymaga zatwierdzenia, co musi zostać zapisane - a Bernstein ją egzekwuje i tworzy weryfikowalny zapis. Deterministyczny scheduler - bez modelu w pętli koordynacji - uruchamia agentów równolegle, filtruje ich wyniki bramkami i zapisuje każdy krok, więc przebieg można zweryfikować po fakcie, offline, wyłącznie z artefaktów. Agenci CLI do kodu działają od ręki (Claude Code, Codex, Gemini CLI i 40+ innych), a ta sama warstwa governuje dowolne obciążenie agentowe: rezultatem może być diff, raport badawczy, dataset albo pakiet dowodów audytowych. Profil instalacji air-gap w zestawie. Apache-2.0.

w skrócie

Cztery cechy wyróżniają ten projekt; reszta to szczegóły.

  • Brak LLM w pętli koordynacyjnej. Harmonogramowanie jest napisane w czystym Pythonie, dzięki czemu każdy przebieg jest w pełni powtarzalny. Odtwórz wczorajszy plan i uzyskaj identyczny graf zadań.
  • Weryfikowalność po fakcie. Dziennik powtórzeń (replay journal) rejestruje każdy przebieg, a stale aktywny kręgosłup pochodzenia (lineage spine) zapisuje każdy krok tworzący historię pochodzenia; opcjonalny dziennik audytu powiązany łańcuchem HMAC (BERNSTEIN_AUDIT=1) dodaje pokwitowania (receipts), które można zweryfikować w trybie offline. Niedeterminizm ujawnia się jako niezgodność skrótu w konkretnym kroku, a nie jako losowy błąd ponownego uruchomienia. Rezultaty inne niż kod podlegają tym samym regułom: zadanie może zadeklarować kontrakt artefaktu (raport, zbiór danych, dziennik działań, wynik operacyjny) i kończy się podpisanym pokwitowaniem pochodzenia zamiast commita git.
  • Izolacja na poziomie architektury. Każde zadanie programistyczne otrzymuje własny git worktree za bramkami scalania (merge gates); zadania w trybie artefaktów otrzymują katalog roboczy w .sdd/workspaces/. Domyślnie agenci nie współdzielą modyfikowalnej przestrzeni roboczej; jedynym współdzielonym stanem jest rejestr zadań (backlog), rezerwowany atomowo. Bardziej rygorystyczna ochrona systemu plików jest opcjonalna dzięki backendom sandbox. Po wyłączeniu worktrees każde zadanie wykonuje się we wspólnym katalogu roboczym.
  • Szeroki wachlarz i lokalne działanie. Ponad 40 adapterów agentów CLI oraz ogólny wrapper --prompt, stan oparty na plikach, brak zależności od chmury SaaS, brak zewnętrznych platform przetwarzania danych.

Pełna lista znajduje się na stronie możliwości; macierz funkcji stanowi wyczerpujący spis.

jak wygląda przebieg

Jeden plik YAML deklaruje cały przebieg: fazy, role, zależności i warunki, pod którymi węzeł w ogóle się uruchamia. Scheduler wykonuje go jako czysty Python - nic w pliku nie jest promptem i żaden model nie decyduje, co dalej. Ten graf buduje pakiet dowodów audytowych; pełny plik leży w .bernstein/workflows/audit-evidence-pack.yaml.

name: audit-evidence-pack
version: "1.0.0"

phases:
  - name: scope
    allowed_roles: [manager, architect]
  - name: collect
  - name: validate
    allowed_roles: [qa, security]
  - name: deliver
    allowed_roles: [security, manager]

nodes:
  define-control-inventory:
    phase: scope
    role: architect

  collect-audit-logs:
    phase: collect
    role: security
    depends_on: [define-control-inventory]

  # three more evidence streams collect in parallel:
  # collect-sboms-and-attestations, collect-runbooks-and-policies,
  # collect-eval-results

  assemble-pack:
    phase: validate
    role: docs
    depends_on:
      - collect-audit-logs
      - collect-sboms-and-attestations
      - collect-runbooks-and-policies
      - collect-eval-results

  mock-auditor-pass:
    phase: validate
    role: qa
    depends_on: [assemble-pack]

  remediate-findings:
    phase: collect
    role: docs
    depends_on:
      - source: mock-auditor-pass
        condition: "status == 'failed'"
    retry:
      max_attempts: 3
      until: "status == 'done'"

  sign-and-deliver:
    phase: deliver
    role: security
    depends_on:
      - source: mock-auditor-pass
        condition: "status == 'done'"
flowchart LR
    inv[define-control-inventory] --> logs[collect-audit-logs]
    inv --> sbom[collect-sboms-and-attestations]
    inv --> rb[collect-runbooks-and-policies]
    inv --> ev[collect-eval-results]
    logs --> pack[assemble-pack]
    sbom --> pack
    rb --> pack
    ev --> pack
    pack --> gate{mock-auditor-pass}
    gate -->|failed| fix["remediate-findings (retry x3)"]
    gate -->|done| sign[sign-and-deliver]
Loading

Każdy węzeł przejmuje agent, którego rolę dopuszcza faza; ogrodzenia ról i bramki zatwierdzeń trzymają niezależnie od tego, co agent robi w zadaniu. Węzeł kodowy kończy się za merge gates we własnym git worktree. Węzły powyżej kończą się inaczej: kontrakt artefaktu nazywa rezultat (raport, dataset, skan, log działań), a węzeł zamyka podpisany kwit lineage zamiast commita. Ten sam scheduler, ten sam journal, ta sama weryfikacja offline - niezależnie czy graf niesie kod, badania, zmianę ops czy miks wszystkich trzech. Gotowe grafy dla softu, badań, dokumentacji, enterprise i procesów kontrybutorskich leżą w .bernstein/scenarios/.

instalacja w 30 sekund

uv tool install bernstein    # or: pipx install bernstein
bernstein init
bernstein doctor             # checks a CLI agent is installed and authenticated
bernstein -g "fix the failing test in tests/test_foo.py"

pipx, pip, brew, dnf, npm oraz Docker zostały opisane w przewodniku instalacji; izolowany pakiet instalacyjny posiada dedykowany przewodnik air-gap.

A real bernstein demo run: mock agents fix four seeded bugs, ending on the run's signed receipt verifying offline

Powyższe nagranie przedstawia rzeczywiste wykonanie i zawiera własny dowód poprawności. Zapis sesji, podpisane pokwitowanie wygenerowane z dziennika tego przebiegu oraz klucz publiczny znajdują się w docs/assets/demo-run/. Zweryfikuj obejrzany przebieg w trybie offline:

bernstein verify receipt docs/assets/demo-run/run-receipt.json \
    --public-key docs/assets/demo-run/run-receipt.pub.pem

System CI weryfikuje zatwierdzone pokwitowanie przy każdym wypchnięciu do gałęzi main — wykazując, że zmodyfikowana kopia nie przechodzi testu — dzięki czemu opublikowany dowód nie staje się bezużytecznym plikiem. Skrypt scripts/record_demo.sh generuje nagranie, pokwitowanie i klucz na nowo z rzeczywistego przebiegu; nic w terminalu nie jest symulowane.

Trwający przebieg można obserwować w dowolnym interfejsie operatora. Oba korzystają z tego samego API zadań, dzięki czemu żaden nie prezentuje opóźnionego stanu. W bernstein live lewa i prawa kolumna przewijają się niezależnie jako całe panele, co zapewnia dostęp do widżetów na mniejszych terminalach.

A two-column terminal dashboard - agents with their live logs on the left, the task board on the right - with a full-width activity feed and a cost line underneath A browser dashboard listing sixty-two tasks with eleven running, one of them opened to its working-tree diff
bernstein live — panel w terminalu bernstein gui serve — panel w przeglądarce

udowodnij poprawność przebiegu

Determinizm w tym projekcie można sprawdzić, zamiast przyjmować go na wiarę. Uruchom zadanie z włączonym audytem, a następnie zweryfikuj zarejestrowane dane:

BERNSTEIN_AUDIT=1 bernstein -g "fix the failing test in tests/test_foo.py"
bernstein replay list                 # run ids recorded on disk
bernstein replay latest --verify      # recompute the journal head, name the first divergent step
bernstein lineage verify <run_id>     # recompute the always-on lineage spine
bernstein audit verify                # HMAC chain + Merkle seal (written because audit was enabled)
bernstein audit diagnose <run_id> --signal gate --sign-key KEY
                                      # name the exact step a failure entered the run, as a signed receipt
bernstein verify run <run_id> --signing-key-path key.pem   # sign one portable run receipt
bernstein verify receipt .sdd/runs/<run_id>/run-receipt.json  # verify it offline: file only

Dziennik jest zapisywany przy każdym uruchomieniu; kręgosłup pochodzenia jest stale aktywny i dodaje wpis dla każdego kroku tworzącego historię, dzięki czemu krótki przebieg może zakończyć się poprawnym, pustym kręgosłupem. Komenda bernstein audit verify sprawdza łańcuch tylko wtedy, gdy uruchomienie nastąpiło z flagą BERNSTEIN_AUDIT=1, profilem zgodności lub bernstein run --audit. Flaga --audit dotyczy polecenia bernstein run; w przypadku formy bernstein -g należy ustawić zmienną środowiskową.

Pokwitowanie przebiegu łączy nagłówek dziennika, nagłówek pochodzenia (jeśli zapisano wpisy) oraz opcjonalnie zakres łańcucha audytu w ramach jednego rekordu podpisanego kluczem Ed25519 z osadzonym kluczem publicznym. Weryfikator dysponujący tym plikiem oraz kluczem publicznym operatora może potwierdzić brak modyfikacji: bez konieczności posiadania klucza HMAC, bez aktywnego katalogu .sdd/, z kodem wyjścia 2 wskazującym pierwszy niezgodny krok w razie manipulacji. Pokwitowanie to identyfikuje stan dziennika; udowodnienie, że stan ten stanowi pełny, ukończony dziennik, wymaga dodatkowo niezależnej pieczęci nagłówka/liczby kroków. Bez wskazania klucza --public-key następuje jedynie weryfikacja spójności wewnętrznej. Szczegóły w deterministycznym odtwarzaniu.

Taka sama weryfikowalność dotyczy wyników benchmarków. Polecenie bernstein bench run <suite> --reliability k (dostępne także jako bernstein eval --reliability k) uruchamia każde zadanie k razy przy stałej koordynacji, raportując dolny próg pass^k (wszystkie k prób musi zakończyć się sukcesem) obok górnego pass@1. Wynik zostaje przypieczętowany w podpisanym pokwitowaniu przeliczanym offline przez bernstein bench reliability-verify, co uniemożliwia sfałszowanie wskaźników. Szczegóły: próg niezawodności pass^k.

jak to działa

Każdy cel realizowany jest w czterech etapach:

  1. Dekompozycja (Decompose). Menedżer dzieli cel na zadania z przypisanymi rolami, plikami i sygnałami ukończenia. Jedno wywołanie LLM, a dalej wyłącznie czysty Python.
  2. Uruchomienie (Spawn). Agenci rozpoczynają pracę w izolowanych git worktrees, po jednym na zadanie programistyczne; zadania w trybie artefaktów otrzymują standardowy katalog roboczy. Główna gałąź pozostaje nienaruszona.
  3. Weryfikacja (Verify). Moduł weryfikacji (janitor) sprawdza twarde kryteria: powodzenie testów, obecność plików, poprawność lintera i zgodność typów.
  4. Scalenie (Merge). Zweryfikowane zmiany trafiają do gałęzi main. Nieudane zadania są ponawiane lub przekazywane do innego modelu.

Dlaczego harmonogram został zaimplementowany w czystym Pythonie i jakie niesie to kompromisy: dlaczego determinizm.

codzienne polecenia

cd your-project
bernstein init                    # creates .sdd/ workspace, bernstein.yaml + templates/
bernstein -g "Add rate limiting"  # agents spawn, work in parallel, verify, exit
bernstein live                    # watch progress in the TUI dashboard
bernstein run plan.yaml           # multi-stage plan: skip LLM planning, execute directly
bernstein stop                    # graceful shutdown with drain

Pełny zestaw funkcji operatora (automatyzacja PR, harmonogramy, integracje czatu, demon autofix) znajduje się w poleceniach operatora.

bernstein workflow uruchamia deklaratywne grafy DAG w formacie YAML złożone z węzłów agent / command / loop — ze wsparciem dla wznawiania przerwanych przebiegów:

bernstein workflow run idea-to-pr -g "Add JWT auth"   # prints run_id
bernstein workflow resume <run_id>                    # picks up at the first non-completed node

Punkty kontrolne stanu przebiegu trafiają do .sdd/runs/<run_id>/ przy każdym węźle. Wznowienie weryfikuje skrót manifestu na starcie przebiegu, więc zmieniona specyfikacja zostaje odrzucona, zamiast po cichu wykonać inny manifest. Zobacz manifesty workflow.

Bramki jakości repozytorium: bernstein readme-l10n verify odrzuca PR, w którym przetłumaczone pliki README odbiegają od wersji angielskiej (wskazując zdezaktualizowaną sekcję), natomiast bernstein readme-l10n sync aktualizuje powiązania po zmianach w tekście źródłowym. Zobacz readme-l10n.

obsługiwani agenci

Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI, Cursor, Aider, Goose, Muse Code, OpenAI Agents SDK, Amp, Cody, Continue, Devin Terminal, Junie, Kilo, Kiro, AWS Q Developer, Ollama, OpenCode, OpenHands, Open Interpreter, gptme, Plandex, AIChat, Letta Code, Qwen i inni. Indeks adapterów zawiera instrukcje instalacji dla 30 z nich. Polecenie bernstein integrations list wyświetla wszystkie 54 wbudowanych integracji z pliku src/bernstein/adapters/registry.py, będącego jedynym źródłem prawdy. 52 z nich to adaptery agentów; pozostałe dwie pozycje to moduł testowy mock oraz profil punktów końcowych self-hosted-endpoints. Wszystkie inne narzędzia obsługujące flagę --prompt działają poprzez uniwersalny wrapper.

Możesz łączyć różnych agentów w ramach jednego przebiegu: tańsze modele lokalne do kodu powtarzalnego, bardziej zaawansowane modele chmurowe do architektury. Polecenie bernstein integrations list --installed wyświetla narzędzia dostępne w systemie.

wolontariacka moc obliczeniowa

Projekt może oznaczyć zgłoszenia jako otwarte dla wolontariuszy, a każdy może uruchomić jedno z nich na własnej maszynie, bez konta i bez koordynatora. To, co zadaniu wolno robić, projekt deklaruje w manifeście volunteer.json - backend piaskownicy, lista dozwolonych adresów sieciowych, limity czasu i pamięci - a własne limity darczyńcy mogą to tylko zawęzić, nigdy poszerzyć. Pokwitowanie ukończonego zadania wiąże wynik z decyzją o izolacji, pod którą powstał, więc opiekun projektu jeszcze po miesiącach może sprawdzić, do czego praca faktycznie miała dostęp.

bernstein volunteer verify .
bernstein volunteer browse --budget 60

Przewodnik darczyńcy opisuje uruchamianie workera i budżet, który ustawiasz, przewodnik projektu - deklarowanie manifestu, a model zagrożeń mówi, przed czym każda granica chroni, a przed czym nie. Uruchamianie jedną komendą nie zostało jeszcze wydane: dziś działają podkomendy verify, browse i hub.

poza stroną główną

Szczegółowa dokumentacja znajduje się w serwisie dokumentacji:

strona zakres tematyczny
capabilities pełna lista możliwości: tryb serwera MCP, podpisane karty agentów, backendy sandbox, miejsca zapisu artefaktów, zgodność regulacyjna
who this is for gdzie tkwi wartość i w jakich sytuacjach Bernstein nie jest odpowiednim narzędziem
workflows deklaratywne grafy DAG w formacie YAML złożone z węzłów agent / command / loop
web UI panel przeglądarkowy korzystający z tego samego API co TUI
cloud execution funkcja eksperymentalna: uruchamianie agentów w Cloudflare Workers z synchronizacją przestrzeni roboczej w R2 na własnym koncie. Usługa hostowana api.bernstein.run nie jest jeszcze publicznie dostępna
datasources pokwitowania zapytań tylko do odczytu oraz sterownik wiążący każdy wynik ze zrzutem schematu
agent catalogs przypisywanie ról do zewnętrznych definicji agentów — uniwersalne katalogi YAML/SKILL.md lub struktury wtyczek Claude Code
security scorecard, fuzzing, utwardzanie
architecture zasada działania od strony technicznej

skąd taka nazwa?

Projekt nazwano na cześć Leonarda Bernsteina, amerykańskiego dyrygenta i kompozytora. Koordynuje on zespół agentów CLI niczym Bernstein orkiestrę New York Philharmonic: każdy muzyk wchodzi we właściwym momencie, partytura jest deterministyczna, a dyrygent odpowiada za efekt końcowy.

stworzyłem bernsteina, ponieważ płaciłem 400 dolarów miesięcznie za rachunki w claude, uruchamiając trzy agenty równolegle i uzyskując niedeterministyczne scalenia. Licencja Apache 2.0, projekt rozwijany jednoosobowo. Statystyki na żywo: bernstein.run.

wzmianki

Projekt wymieniony w vinta/awesome-python, omówiony w zestawieniu orkiestratorów agentów open source przygotowanym przez Augment Code oraz wskazany w Python Weekly #742. Opisaliśmy to podejście również jako wzorzec deterministycznej orkiestracji bez LLM w repozytorium awesome-agentic-patterns.

Wszystkie wzmianki: ponad 20 zestawień awesome, katalogów, newsletterów i cytowań

Pełna lista publikacji, w tym wpisy w spisach awesome, katalogach oraz wzmianki w biuletynach, znajduje się w pliku docs/mentions.md. Nowe wpisy są dodawane na bieżąco; poprawki można zgłaszać poprzez issue lub PR.

współpraca, wsparcie, licencja

Propozycje zmian (PR) są mile widziane; plik CONTRIBUTING.md zawiera zasady konfiguracji i stylu kodu. Zgłoszenia dotyczące bezpieczeństwa przyjmujemy poprzez SECURITY.md. Jeśli Bernstein oszczędza Twój czas: GitHub Sponsors. Kontakt: forte@bernstein.run.

Metadane cytowania znajdują się w CITATION.cff. Licencja: Apache-2.0; nazwa projektu podlega odrębnym zasadom w TRADEMARKS.md.


Alex Chernysh · GitHub · X · bernstein.run