Skip to content

Справочник API

Символы верхнего уровня, экспортируемые reactifact (см. reactifact/__init__.py). Формат по группам: имя — роль в одну строку. Детали — в док-строках модулей — см. автосгенерированный референс (только на английском, докстринги в коде не переведены): сигнатуры, типы и полный текст докстринга рендерятся прямо из исходников на сайте документации, а не копируются сюда вручную.

Стабильность

reactifact всё ещё pre-1.0 (0.20.1), но не rc — поверхность ниже это стабильный контракт, а не движущаяся цель. Он проверяется машиной: tests/test_public_api.py фиксирует каждый __all__, перечисленный здесь, поэтому новый экспорт добавляется осознанно (и документируется на этой странице), а не случайно.

  • Публичный API = каждое имя в reactifact.__all__ (и в __all__ каждого подмодуля — reactifact.recipes, reactifact.providers, reactifact.viz, reactifact.eval, reactifact.tracing, reactifact.quick, reactifact.redaction, reactifact.audit, …) — это ровно тот набор символов, что задокументирован на этой странице и зафиксирован freeze-тестом. Если что-то импортируется из reactifact, но не входит в __all__ — это внутренняя деталь без гарантий совместимости. Например, reactifact.relations.RelationGraph и reactifact.commit_log.CommitLog существуют потому, что Context разбили на модули поменьше ради читаемости, но ни один из них не экспортируется: поддерживаемая поверхность — это Context, а не они.
  • SemVer в pre-1.0-стиле: минорный бамп (0.20.1 → 0.21.0) может добавить символы или, в редких случаях, изменить поведение так, что CHANGELOG.md явно пометит это Breaking — минорные релизы до 1.0 всё ещё позволяют reactifact исправить архитектурную ошибку. Патч (0.14.0 → 0.14.1) никогда не убирает и не переименовывает публичный символ и никогда не меняет задокументированное поведение — только чинит баги относительно него.
  • Депрекейшен: символ на пути к удалению остаётся импортируемым и работает минимум один минорный релиз; он помечается deprecated в docstring и в CHANGELOG.md (с заменой) до любого удаления, а удаление происходит только в минорном релизе под заголовком ### Breaking.
  • Любое ломающее изменение помечено в CHANGELOG.md заголовком ### Breaking, даже в pre-1.0 релизе — см. release.md. Если перед апгрейдом читать только один раздел — читайте этот.
  • 1.0 означает, что эта страница замирает: критерии релиза — это планка выхода из pre-1.0; после него действует SemVer 1.x (никаких ломающих изменений в миноре).
  • Всё, что находится под reactifact.cli.* за пределами задокументированных подкоманд python -m reactifact …, а также любые тест-хелперы модулей — деталь реализации, даже если формально импортируется.

Он-рамп (reactifact.quick)

Тонкий сахар над примитивами ниже для четырёх частых первых задач — у каждого объекта есть настоящий .agent/.agents и .context запуска, поэтому он выпускается в Consume/Step/Effects без переписывания. См. Быстрый старт §0.

Символ Роль
agent(system, schema) один структурированный вызов LLM → один типизированный артефакт
rag(sources) поиск → материализация → ответ, с провенансом supported_by
tools_agent(system, tools, human=False) LLM + тулы (human=True → HITL-вопросы)
chat_agent(agents) настроенный ChatAssistant (по умолчанию store в памяти)
Question / Doc / Answer обобщённые модели артефактов, которые использует фасад

Context и состояние

Символ Роль
Context версионируемое рабочее состояние; ресурсы; request (per-request mapping активного хода); запросы; latest(Model); announce; diff/rollback; compact(keep_commits=, keep_versions=) для ограничения истории (compacted_at); apply_commit(commit) проигрывает коммит в живое состояние (путь загрузки append-only сессии)
View результат типа-запроса (context.view(...))
RuntimeResources провайдеры + источники + ресурсы приложения; register(Type, instance) / get(Type) / require(Type) / has(Type) для типизированных коллабораторов (ResourceKey[T], когда их два одного типа); строковые get/set остаются escape hatch'ом (additional); redactor= вычищает текст трейсов; trace_truncate= ограничивает JSON артефактов/ответов в трейсе (None — без обрезки) — deprecated fallback (даёт DeprecationWarning), лучше TraceLimits(max_data_chars=…); await resources.aclose() закрывает HTTP-клиенты llm/embedder (duck-typed) — вызывайте сами при завершении; record_tool_args=True пишет аргументы тулов в ToolRun (вычищаются redactor=)
ResourceKey[T] типизированный ключ для регистрации двух ресурсов одного типа (primary/replica, per-tenant)
ResourceScope / RuntimeResources.scope(factory) async with-билдер: создаёт ресурсы на текущем loop и закрывает на выходе — loop-safe способ владеть провайдерами
current_request() request-маппинг активного хода (то же, что StepCall.request)
Commit, Read, Write учёт версий и записанные операции провенанса

Артефакты и изменения

Символ Роль
Artifact неизменяемый handle (id, version, data, content_hash); история — в Context (artifact_version/version_history/find_versions)
register_type(Model, *, type_id=, aliases=, migrate=) (reactifact.types) стабильная персистентная идентичность типа: переименование/перенос модели больше не ломает загрузку старых сессий/коммитов/событий. type_id_of/resolve/migrate_payload; дефолтный id — qualified name
Patch скомпилированный набор изменений рантайма (транспорт); шаги пишут эффекты (effects/call.effects), Patch собирает рантайм
reactifact.operations (Create/Update/Delete/Link/Unlink/Relation) скомпилированные операции, которые несёт патч (§12)
Create, Update, Delete, Link, Unlink, Relation записи операций, из которых строятся патчи

Агенты и produce

Символ Роль
Agent тонкий контейнер: name, steps, concurrency_limit; триггеры выводятся из consumes шагов
create_agent конструктор-фабрика агента — без подкласса для обычных контейнеров
Wakes(False) / Scope / Consume / consume декларативная (или декоратор) завязка реакции; Consume.by_field для скоуп-событий; Consume.by_base / include_subclasses=True будит на наследниках marker-базы; wakes=False — читать как вход, не будя агента; debounce=True схлопывает несколько событий одного поколения в один запуск
reactifact.consume.CorrelatedConsume срабатывает (и питает входы) только для ключа корреляции, где присутствуют все типы из require и отсутствуют все из forbid — механизм за JoinConsume/AbsentConsume
reactifact.consume.JoinConsume(*parts, key=…) фабрика над CorrelatedConsume: срабатывает, когда для одного ключа существуют все перечисленные типы
reactifact.consume.AbsentConsume(type, absent_type=…, key=…) фабрика над CorrelatedConsume: срабатывает для type, только если для того же ключа ещё нет absent_type
Step / @step единица работы: класс run(...) получает типизированные входы + effects: Effects; функция @step получает call: StepCall и пишет через call.effects. consumes объявляет входы/триггеры, produces — разрешённые Create-типы; возврат модели — create-сахар. Annotated[T, When(...)]/Consume.by_* задают условия; дополнительные create — в том же tuple (produces=(Primary, Extra)); also_creates=/reacts_to= — deprecated алиасы
Trigger вторичное (не артефактное) условие входа produce; context_condition(artifact, context) — для условий, которым нужны другие артефакты (join/корреляция); флаг debounce, который читает Runtime
StructuredGenerateAgent декларативный агент LLM→схема→артефакт (schema, build_prompt, fallback)
LLMAgent блокирующий цикл LLM+инструменты (system, tools, max_steps, deferred_tool_groups)
HITLLMAgent цикл LLM+инструменты с паузами на ответ человека (max_asks, отчёт о возобновлении)
ToolUse, ToolUseHITL produce цикла инструментов; HITL-вариант ждёт одобрения перед исполнением
DeferredToolGroup (reactifact.tools.use) группа инструментов, чьи схемы не попадают в промпт, пока встроенный инструмент load_tools в ToolUse их не запросит (только LLMAgent/ToolUse, не HITL-вариант)
Tool, FunctionTool, tool, ToolOutput, ToolError абстракция и регистрация инструментов; ToolOutput.failed(ToolError(code=, message=, retryable=)) даёт типизированную ошибку, а ToolOutput.error остаётся обычной строкой
ToolAnswer, Observation результаты инструментов и наблюдения модели (протокол цикла)
PendingQuestion HITL-примитив: приостановленный вопрос, ждущий ответа человека, возобновляется через effects.resume(...)
Effects.act(kind, *, key, payload=…) outbox-примитив: записывает намерение PendingAction (стабильный id action:{key}) вместо I/O в produce; None, если уже существует
PendingAction записанный внешний side effect (kind, idempotency_key, payload, status, attempts); выполняется один раз через Runtime(dispatcher=...), затем dispatched / failed (retry_action возвращает в очередь)

Runtime

Символ Роль
Runtime будит агентов по событиям; run / arun / astream (каждый принимает request=Mapping); бюджет и параллельность; isolate_errors=True + on_agent_error(agent, event, exc), чтобы исключение одного агента не обрывало весь запуск (по умолчанию — пробрасывается, §69); dispatcher=async (context, action) дренирует outbox PendingAction после каждого коммита (один раз на стабильный id, удерживая ход живым, пока outbox не пуст); on_dispatch_error(action, exc) срабатывает, когда диспетчер падает (действие помечается failed, исключение пробрасывается); flush_pending_actions() дренирует без поколения (например, после merge()); Budget.max_seconds — жёсткий дедлайн хода (отменяет генерацию в полёте)
Runtime.request_stop() / await ashutdown(timeout=…) / in_flight graceful shutdown: остановка на границе генерации (RunOutcome.STOPPED; текущая генерация доигрывается); ashutdown ждёт ход, форс-отменяя по timeout
reactifact.runtime.active_runs() / cancel_run(run_id) read-only снимки активных ходов процесса (RunInfo) и точечная отмена — readiness/ops, только внутри процесса
StepCall.request request-маппинг хода внутри шага (Runtime.arun(request=…) / ChatAssistant.stream(request=…)); пустой, если не задан
Budget, RunOutcome, RunStats, BudgetTracker лимиты запуска (max_runs/max_iterations/max_seconds/max_tool_calls/max_tokens/max_cost) и итог/статистика usage (RunOutcome включает budget_time_exceeded и stopped). Лимиты токенов/стоимости считают usage LLM без трейсера; для стоимости нужен инжектированный Pricer (reactifact.pricing)
Event, EventType проводной формат «что-то изменилось» — ARTIFACT_CREATED/UPDATED/DELETED/STALE
EventHub, ProgressEvent канал прогресса/announce, который потребляют web-UI
Scheduler политика выбора агента filter → rank → LLM tie-break, вызывается рантаймом на каждой итерации (см. design notes, пока только на английском)
uncertainty_policy(...) собирает встроенную гибридную политику Scheduler (filter → rank → LLM tie-break → top-k)

Логи (reactifact.logging)

Символ Роль
configure_logging(level="INFO", *, json=False, stream=None) включает коррелированные структурные логи в reactifact.* — молчит, пока не вызван; json=True → по одному JSON-объекту на строку
get_logger(name) логгер, подмешивающий в каждый record поля корреляции хода (run_id/session_id/generation/agent/request_id)
bind(**fields) добавляет доменные поля корреляции на блок (tenant, user, …)

Чат-слой (reactifact.chat + reactifact.web)

Символ Роль
ChatAssistant сессии + цикл хода + история в одном handle (stream/invoke/history); хуки: agents, user_message, reply, session_state; dispatcher=/on_dispatch_error= пробрасываются в Runtime (outbox-эффекты прямо из чат-хода)
ChatMemory необязательная ограниченная память для ChatAssistant, поля независимы: keep (обрезать сырой поток), summarize+summary_type (растущий дайджест), compact_commits (Context.compact — ограничивает историю, не трогая артефакты); message_types=[UserQuery, Answer] (или marker-база) ограничивает гетерогенный поток
ChatEvent один транспорт-нейтральный фрейм; kind — закрытый Literal["session","status","message"], схема интроспектируема
run_message(runtime, text, *, user_message, reply) строительный блок хода: создать вход → стримить статусы → терминальный ответ
default_session_state(ctx, user_message) универсальный читатель истории (любой артефакт с .text)
create_chat_router(assistant, *, event_names=…, forward_kinds=…, payload_shaper=…, done_event=…, request_factory=…) FastAPI APIRouter SSE-контракта (/api/chat/stream, /api/runs/{id}, /api/health) — нужен extra web. Словарь wire-событий настраивается (переименовать kinds, отфильтровать, изменить payload, добавить терминальный фрейм); request_factory(request) строит request-маппинг хода из FastAPI Request (ходы с учётом идентичности/ACL); схема событий публикуется в OpenAPI responses маршрута
reactifact.web.sse(event, data) один SSE-фрейм

Визуализация (reactifact.viz + python -m reactifact)

Символ Роль
blueprint(agents) статическая карта consumes/produces как Mermaid flowchart
context_to_mermaid(context) живой граф провенанса контекста (артефакты + связи)
trace_to_mermaid(trace) один запуск как Mermaid sequenceDiagram
python -m reactifact graph\|context\|trace CLI, печатающий диаграммы в stdout
trace_provenance_to_mermaid(trace) граф доказательств запуска (записанные артефакты + рёбра patch.link)

Replay (reactifact.replay, §55)

Символ Роль
ReplayLLM(recording, mode="record"\|"replay", inner=…) записывает каждый LLM-вызов в JSONL или воспроизводит их точно; ReplayMiss при расхождении
ReplayMiss воспроизводимый вызов не совпал с записью
verify_run(build, *, recording=None, repeat=2) прогоняет build(resources) -> Context repeat раз под записанной моделью и строгими id (counter_ids), возвращает ReproReport; ok=False, если context_hash разошёлся (реальная недетерминированность)
counter_ids() детерминированный id_factory (Model:0000, Model:0001, …) для RuntimeResources(id_factory=…) — делает артефакты без явного id воспроизводимыми
replay_context(store, session_id, version=None) восстанавливает состояние сохранённой сессии на коммите
replay_summary(context) компактная сводка состояния для CLI replay — включает dispatched_actions / pending_actions / failed_actions (replay никогда их не пере-отправляет)

Ветвление (reactifact.context + reactifact.branching, §39-§40)

Символ Роль
Context.branch(name="") форкает изолированную копию; фиксирует снимок базы для трёхстороннего слияния
Context.merge(other, message=…) атомарное трёхстороннее слияние; MergeConflict при разошедшихся артефактах
MergeConflict бросается, когда обе стороны изменили артефакт по-разному после форка
BranchStore(KVBackend) хранит ветки как branch:<session>:<name> поверх KV-бэкенда
python -m reactifact branch … CLI: list / save / merge

Оценка (reactifact.eval, §56)

Символ Роль
run_suite(cases, metrics) / run_case(case, metrics) выполнить кейсы и скорить итоговые контексты
EvalCase / EvalResult / EvalReport / Metric структуры кейс/скор/отчёт (overall(), aggregate(), passed(), render(), to_dict())
core_metrics четыре не генеративные метрики (answer/provenance/evidence/claim)
answer_coverage() · calculation_correctness(values=…) · source_coverage() · confidence_calibration() фабрики с грёд-трусом (skip при отсутствии expected)
Dataset / Example версионируемые примеры (from_file/from_list, .json/.jsonl, content-hash version)
evaluate(dataset, target, evaluators, *, extract=…, summary=…, max_concurrency=…, on_result=…) / aevaluate прогон target по каждому примеру со скорингом; target возвращает Context, ScenarioResult, mapping выходов или RunResult; on_result(result) отдаёт каждый посчитанный EvalResult (при конкурентности — в порядке завершения)
ResultCallback type alias Callable[[EvalResult], None] для прогресс-хука on_result
from_metric(name, metric_fn) обернуть метрику скоринга в Evaluator
trajectory_match(mode, *, steps=…, reference_key=…) сопоставить путь прогона (strict/unordered/subset/superset) по agents/events/reads/writes
llm_judge(llm, *, instructions, …) · judge_correctness · judge_relevance · judge_faithfulness эвалуаторы LLM-as-judge (continuous/choices/include_reference)
summary_pass_rate(threshold) / summary_mean(key) · assert_eval(report, …) агрегаторы по сюиту и CI-гейт
OnlineEvaluator(store, config, metrics=, on_report=) · online_evaluate(store, config, metrics=) · OnlineEvalConfig оценка живых прогонов из TraceStore; run_once() / run_forever(interval)
trace_source() · context_source(run_fn) · output_present(key) · no_errors() что оценивать: сам трейс, восстановленный Context, выводы, спаны
create_online_eval_router(evaluator) FastAPI-роутер: POST /api/evals/run, GET /api/evals/report, GET /api/evals/summary
python -m reactifact eval <traces.db> CLI: online-оценка прогонов (теги результатов, --evaluators trace\|judge\|all)

Структурный вывод

Символ Роль
structured_llm(context, schema, *, system, user, attempts=…, validate=…, repair=…, prompt_hash=…, on_error=…) один структурный вызов; None при честном сбое; validate(model)->bool добавляет домен-проверку, повторяемую как parse-сбой; repair(invalid_or_None, last_reply)->str даёт инструкцию для повтора; on_error(reason, exc) ("no_provider"|"provider_error"|"parse_error"|"validation_error") — понять почему, не меняя контракт None
json_schema_llm(context, json_schema, *, user, validate=…, repair=…, …) структурный вывод по собственной JSON Schema (dict или JSON-строка), возвращает обычный dict; те же хуки повтора validate/repair, что у structured_llm
StructuredLLM(schema, *, system=…, attempts=…, on_error=…) переиспользуемый экземпляр; .call(context, user)
llm_reply(context, *, system, user, attempts=…, on_error=…) обычный (неструктурный) вызов → str или None (под капотом схема с одним полем)
parse_structured допускающий JSON→модель парсер, используемый внутри

Промпты (reactifact.prompts, §68)

Символ Роль
PromptTemplate(template, *, defaults=…) строгий рендер {var}: объявленные variables, KeyError при нехватке, поля атрибутов модели ({question.text}); подставляются только placeholder'ы-идентификаторы — литеральный JSON {"name": …} / {} в промпте остаётся как есть, без экранирования; .hash — стабильный sha256 шаблона
MessagesPrompt([(role, template), …]) рендерит чат-последовательность в list[Message]; .hash покрывает все строки

Источники (reactifact.sources)

Символ Роль
Source ABC: asearch(query, limit) → list[SourceRef]
SourceRef общий атомарный результат поиска (ранжирован, скоуп, стабильный id)
FileSystemSource поиск по ключевым словам/эмбедингу по локальным файлам
CSVSource детерминированный поиск по каталогу/таблице
EmbeddingSource векторный поиск по подготовленному корпусу
WebSource открытие ресурсов + ленивое разрешение удалённых документов

Провайдеры (reactifact.providers)

Каждый провайдер лениво создаёт httpx.AsyncClient и перепривязывает его к текущему event loop, поэтому один экземпляр провайдера переживает повторные asyncio.run(...) и per-test loop'ы (без RuntimeError: Event loop is closed); aclose() закрывает клиент текущего loop. То же — для WebSource и OTLP/Langfuse-приёмников.

Символ Роль
LLMProvider, EmbeddingProvider два контракта, с которыми говорит ядро
ImageProvider, SpeechProvider, TranscriberProvider, VideoProvider медиа-контракты
OpenAICompatProvider, OpenAICompatEmbedder + вендорные фабрики (openai_llm, anthropic_llm, deepseek_llm, groq_llm, mistral_llm, openrouter_llm, gemini_llm, ollama_llm, azure_llm, …) 20+ чат/эмбеддинг-бэкендов, у всех retry_attempts=3 по умолчанию (429/5xx/сетевые ошибки, экспоненциальный backoff — никогда на 4xx)
openrouter_embedder, openrouter_speech, groq_transcriber, together_embedder, fireworks_embedder, qwen_embedder, nvidia_embedder эмбеддинги/TTS/STT для вендоров, чьи не-чат эндпоинты подтверждённо OpenAI-совместимы (см. providers)
Message, Role одно сообщение чата; role — закрытый Literal + фабрики Message.system/user/assistant/tool
LLMRequest одна генерация: messages + temperature/max_tokens — None = дефолт провайдера (вызов перекрывает провайдера, провайдер None = поле не отправляется)
LLMResponse, LLMResponseChunk результат одной генерации / один поточный чанк, возвращаемые провайдером
*_from_env(**overrides) подключение из .env; возвращает None, если не настроено
CachingLLM, KVCache (reactifact.cache) точный кэш complete(): повторный запрос отвечается без провайдера (cache= — для персистентности), хит не списывается бюджетом; не семантический, stream() не кэшируется
RouterLLM, retryable_only (reactifact.routing) failover провайдеров: пробует по порядку, переходит при сбое (should_fallback=/on_fallback=); только complete()
from_env(**overrides) выбор в один вызов: сперва OPENROUTER_API_KEY, иначе OPENAI_BASE_URL, иначе None — тот самый двухветочный дефолт, что каждый пример вручную собирает в своём build_llm()
FakeLLM, FakeEmbedder детерминированные заглушки для тестов/демо

Рецепты (reactifact.recipes)

Символ Роль
find(inputs, Model) / find_all(inputs, Model) типизированный поиск в inputs шага без next(... isinstance ...)
fan_out_sources(context, query, owner_id, …) идемпотентный поиск fan-out → рефы + патч
materialize_doc(context, ref_artifact, doc_factory, relation=…) ленивый реф → документ с провенансом
StatusMachine / StatusState детерминированный жизненный цикл артефакта: next_status(state) по входам, отфильтрованным по ключу (all/any/latest), terminal, on_transition
WindowSummarizer(message_type, artifact_type, summarize=…, build=…) периодическая суммаризация окна диалога, идемпотентна по числу сообщений; message_type может быть последовательностью типов
WindowPruner(message_type, keep=…) удаляет сообщения старше окна; полезен и сам по себе; message_type может быть последовательностью типов
Conversation / ConversationMessage / create_turn / transcript многоходовой разговор, обобщённый над моделью сообщения (вашей или дефолтной ConversationMessage): добавлять ходы, рендерить поток в провайдерские Message (хелперы turn_count / conversation_state)
Transcript / MessageSpec read-only view для приложений с разными типами на стороны (MessageSpec(Question, "user"), MessageSpec(FinalResponse, "assistant", render=…)): сливает типизированные ходы по ролям в один Message-список (messages / state)
llm_summarizer(system=…) строит колбэк WindowSummarizer(summarize=…) из системного промпта через llm_reply
run_tool_loop(context, *, system, user, tools, max_rounds=…, parallel=True, mandatory=…, max_observation_chars=…, redact_tool_outputs=False, retry_tool_errors=False, tool_retry_attempts=2, tool_retry_delay=0.5, parse_calls=…, fallback=…, on_event=…) opt-in цикл native tool-calling поверх reactifact.tools.native: ограниченные раунды, параллельное выполнение тулов, дожим обязательного тула, форсированный финальный ответ; соблюдает Budget хода (max_tool_calls, max_seconds, токены/стоимость); ограничивает наблюдения (max_observation_chars), опционально редактирует их через resources.redactor, повторяет ToolError(retryable=True) при retry_tool_errors=True, принимает parse_calls-кодек (например, текстовый DSML), fallback для markup-ответов и on_event-хук для стриминга; возвращает ToolLoopResult (текст, транскрипт, ToolObservation, stop_reason/error)
looks_like_tool_markup(text) / parse_textual_tool_calls(text) / parse_tool_calls_with_textual(response) opt-in хелперы для провайдеров, отдающих DSML/Hermes/XML-разметку вместо native tool_calls; последний передаётся как run_tool_loop(parse_calls=…)

Хелперы текста и отката (reactifact.recipes)

Символ Роль
keyword_score(text, query, *, stopwords=EN_STOPWORDS, use_stems=False) детерминированный скоринг покрытия запроса (EN/RU)
stem_words(text) / stem(word) стемминг русско-английских токенов без эмбеддингов
EN_STOPWORDS набор английских стоп-слов по умолчанию
changed_fields(old, new, *, ignore=()) какие поля реально изменились (новый None — не изменение)
earliest_stage(changed, *, field_stages, order) первая затронутая изменение стадия (change → rebuild)
downstream_fields(target, *, field_stages, order) поля, которые сбрасывать при пересборке со стадии

Сессии, чекпоинты, трейсинг

Символ Роль
Session, SessionStore долгоживущая память чата между запросами; SessionStore(backend, compact_every=N) ограничивает append-журнал (примерно каждые N сохранений снапшот перезаписывается)
KVBackend, FileKVBackend, SQLiteKVBackend, PostgreSQLKVBackend key/value чекпоинты под сессии (pg extra для Postgres) — async-native: файловый I/O уходит в отдельный поток, SQLite/Postgres держат одно постоянное соединение (WAL + busy_timeout у SQLite) под asyncio.Lock; SQLite/Postgres также реализуют AppendBackend (снапшот + append-only журнал коммитов, сохранение пишет только новые коммиты)
CheckpointBackend, FileBackend, SQLiteBackend чекпоинты всего контекста
Tracer, CompositeTracer, AgentSpan, AgentContract, RunTrace, LLMCall, StepRun (ProduceRun alias), ToolRun, TraceStore примитивы трейсинга (async-приёмники: export/query/get; AgentSpan.event_artifact_type/event_artifact_id — артефакт-триггер, AgentSpan.contract — объявленные consumes/produces/tools/priority, AgentSpan.produces — отработавшие StepRun (ProduceRun alias), а AgentSpan.tools — ToolRun; get(span_limit=…, span_offset=…) постранично читает большой run и отдаёт span_total/has_more_spans/trace_truncated; оба стора умеют delete_run/delete_session)
LangfuseTracer, OTLPTracer, PostgresStore внешние приёмники трейсов — OTLPTracer вендор-нейтральный (GenAI semconv, любой OTLP/HTTP-коллектор), LangfuseTracer заточен под Langfuse, Postgres поддерживает async чтение+запись; дашборд (create_trace_router) принимает любой TraceReader
TraceLimits write-time лимиты трейса для Tracer(..., limits=TraceLimits(max_spans=5000, max_refs_per_span=50, max_llm_calls_per_span=20, max_data_chars=None)); max_data_chars=None берёт legacy-значение из RuntimeResources.trace_truncate; отброшенные данные помечают трейс trace_truncated
TraceColumn настраиваемая колонка таблицы из артефактов для create_trace_router(store, columns=[…]): label, field (точечный путь, список→первый), agent, type (класс или имя), direction read/write/any, index, scope run/session, default
create_trace_router(store, *, max_detail_spans=500, max_mermaid_spans=200, max_concurrent_reads=2) (reactifact.tracing.web) FastAPI-роутер дашборда; detail/diagram ограничены и ленивые, DELETE /api/traces/{id} / DELETE /api/sessions/{id} удаляют run/сессию; страницы prefix-aware (работают под include_router(prefix=…)/ASGI root_path)
Metrics, MetricsTracer, create_metrics_router (reactifact.metrics) Prometheus-метрики без зависимостей: счётчики/гистограммы (runs_total, agent_runs_total, llm_calls_total, llm_tokens_total, llm_cost_total, artifacts_written_total, relations_total, латентности…) из трейс-хука; render() выдаёт text exposition, create_metrics_router отдаёт GET /metrics. RuntimeResources(metrics=…) открывает тот же sink produce'ам (по умолчанию no-op)

Trust & safety (reactifact.guardrails / reactifact.authz / reactifact.quota, §57)

Символ Роль
GuardrailPolicy · PIIGuardrail · InjectionGuardrail · DenyListGuardrail · SizeGuardrail · PatternGuardrail · GuardrailViolation проверки на границе артефактов для данных от агентов; on_violation="block"|"flag", редактирование PII через любой Redactor
Principal · PermissionPolicy · AuthorizationError authz по capabilities на run / create / update / delete / execute
Quota · QuotaTracker · QuotaLLM · QuotaExceeded межходовые лимиты токенов/стоимости/вызовов на principal (RunOutcome.QUOTA_EXCEEDED)
RuntimeResources(principal=, authorizer=, guardrails=, quota=) · resources.authorize/require_authorized/quota_key опциональная обвязка; по умолчанию выключено

Тестирование (reactifact.testing, §56)

Символ Роль
ScenarioLab, Scenario scenario-харнесс: посев артефактов, прогон агентов, ассерты (артефакты/тулы/путь/отношения/llm/ошибки/события), mode= live/record/replay. Инъекция сбоев и заглушек: fail/stub_tool (тулы) и fail_resource/stub_resource (любой ресурс по строковому имени или типизированному Type/ResourceKey), у каждого times/when/delay; у stub_resource — returns/side_effect. run_sync/turn_sync повторяют async-API для обычных тестов
группы ассертов ScenarioResult, Scenario result.artifacts(Type) (.linked(relation, Type) для провенанса), result.relations (has/none/count/outgoing/incoming), result.tools, result.path, result.llm, result.errors, result.events. result.explain() выводит весь прогон
ScenarioReport, ScenarioResult.report, Scenario.report итоги хода (или агрегат по многоходовому scenario): llm_calls, prompt_tokens/completion_tokens/total_tokens, tool_calls, spans, agents, errors, outcomes, с to_dict() и render(). result.llm также даёт prompt_tokens/completion_tokens/tokens
current_result() последний ScenarioResult, произведённый этой задачей — чтобы инструменты (CLI) могли показать состояние прогона, когда падает более поздний ассерт
capture(context, *, trace=…), assert_golden(context, golden, *, trace=…), assert_golden_file(context, path, *, trace=…, update=…) заморозка/сверка GoldenRun; файловый вариант заводит снапшот, если его нет (или update/$REACTIFACT_GOLDEN_UPDATE), а ScenarioResult.assert_golden(path)/Scenario.assert_golden(path) — обёртки над ним
replay_resources(recording, *, base=…) RuntimeResources, чей llm реплеит запись — офлайн-регресс на реальном прогоне
reactifact.testing.pytest_plugin opt-in pytest-плагин (pytest_plugins = ["reactifact.testing.pytest_plugin"]): гоняет async def-сценарии без pytest-asyncio, превращает ScenarioSkip в skip, даёт фикстуру-фабрику scenario_lab

MCP (reactifact.mcp, extra mcp)

Символ Роль
mcp_stdio_tools(command, args), mcp_http_tools(url) подключение к MCP-серверу, отдаёт его инструменты как list[Tool]
mcp_tools(session), MCPTool обернуть инструменты существующей mcp.ClientSession
oauth_client_credentials(server_url, client_id=, client_secret=, issuer=), InMemoryTokenStorage значение auth= для mcp_http_tools — grant client_credentials OAuth (machine-to-machine, без браузера и согласия человека)
create_mcp_server(tools, context=...) отдать Tool (и, с context=, артефакты Context) как mcp.server.mcpserver.MCPServer