AionUi
Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!
Crawler Summary
Практичне завдання №2: мультиагентна система логістики — supervisor у LangGraph, CrewAI та Google ADK над спільним MCP-сервером (FastMCP), guardrails (injection/allowlist/PII), HITL, tracing у LangSmith, deepeval + DeepTeam Мультиагентна система логістики: LangGraph, CrewAI, MCP і security hardening Практичне завдання №2 курсу «Агентні системи». Предметна область варіанта — **логістика та складський облік**: трекінг відправлень, залишки на складах, розрахунок вартості доставки і **скасування відправлення з поверненням коштів** як ризикова незворотна операція. Один і той самий кейс реалізовано **тричі** — у LangGraph (supervisor + 3 ворк Capability contract not published. No trust telemetry is available yet. Last updated 10/9/2026.
Freshness
Last checked 10/9/2026
Best For
goit-aad-hw-10 is best for crewai, multi-agent workflows where OpenClaw compatibility matters.
Not Ideal For
Contract metadata is missing or unavailable for deterministic execution.
Evidence Sources Checked
editorial-content, GITHUB REPOS, runtime-metrics, public facts pack
Практичне завдання №2: мультиагентна система логістики — supervisor у LangGraph, CrewAI та Google ADK над спільним MCP-сервером (FastMCP), guardrails (injection/allowlist/PII), HITL, tracing у LangSmith, deepeval + DeepTeam Мультиагентна система логістики: LangGraph, CrewAI, MCP і security hardening Практичне завдання №2 курсу «Агентні системи». Предметна область варіанта — **логістика та складський облік**: трекінг відправлень, залишки на складах, розрахунок вартості доставки і **скасування відправлення з поверненням коштів** як ризикова незворотна операція. Один і той самий кейс реалізовано **тричі** — у LangGraph (supervisor + 3 ворк
Public facts
4
Change events
1
Artifacts
0
Freshness
Oct 9, 2026
Capability contract not published. No trust telemetry is available yet. Last updated 10/9/2026.
Trust score
Unknown
Compatibility
OpenClaw
Freshness
Oct 9, 2026
Vendor
Alexnodejs
Artifacts
0
Benchmarks
0
Last release
Unpublished
Key links, install path, and a quick operational read before the deeper crawl record.
Summary
Capability contract not published. No trust telemetry is available yet. Last updated 10/9/2026.
Setup snapshot
Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.
Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data.
Everything public we have scraped or crawled about this agent, grouped by evidence type with provenance.
Vendor
Alexnodejs
Protocol compatibility
OpenClaw
Handshake status
UNKNOWN
Crawlable docs
6 indexed pages on the official domain
Merged public release, docs, artifact, benchmark, pricing, and trust refresh events.
Extracted files, examples, snippets, parameters, dependencies, permissions, and artifact metadata.
Extracted files
0
Examples
4
Snippets
0
Languages
python
bash
# 1. Оточення (окремий venv — див. розділ 12, чому не в базовий) uv venv --python 3.13 uv pip install -r requirements.txt # 2. Ключі cp .env.example .env # вписати OPENROUTER_API_KEY і LANGSMITH_API_KEY # 3. Самоперевірки БЕЗ мережі та БЕЗ ключів — усе має пройти .venv/bin/python mcp_server.py --selfcheck # 4 MCP-інструменти, валідатори, JSON-конверт .venv/bin/python guards.py # injection / allowlist / PII / CostTracker .venv/bin/python mas_crewai.py --selfcheck # склад crew і allowlist .venv/bin/python mas_adk.py --selfcheck # структура workflow-пайплайна .venv/bin/python mas_langgraph.py --graph # mermaid-схема графа .venv/bin/python -m pytest test_mas.py -v # 63 тести # 4. Живі запити (потрібен ключ) .venv/bin/python mas_langgraph.py "Де зараз посилка TTN-000001?" .venv/bin/python mas_crewai.py "Скільки ноутбуків SKU-1001 на складах?" .venv/bin/python mas_adk.py "Статус TTN-000001 і залишок SKU-1001" # 5. Human-in-the-loop: граф зупиняється і чекає рішення оператора .venv/bin/python mas_langgraph.py --thread h1 "Скасуй TTN-000004, клієнт відмовився, поверни 720 грн" .venv/bin/python mas_langgraph.py --thread h1 --show-state # інший процес бачить паузу .venv/bin/python mas_langgraph.py --thread h1 --approve # або --reject "занадто рано" # 6. Повний прогін демонстрацій → demo_results.json, costs.json, trace_langsmith.json .venv/bin/python demos.py .venv/bin/python demos.py --only guardrails hitl # 7. Бонуси: evals і red-teaming (результати кешуються, --force перерахує) .venv/bin/python evals.py
text
goit-aad-hw-10/ ├── mcp_server.py # вимога 3: FastMCP-сервер, 4 інструменти + мок-дані домену ├── guards.py # вимога 5: injection / allowlist+валідація / PII + облік вартості ├── mas_langgraph.py # вимоги 1, 6: supervisor + 3 воркери, MCP, HITL, LangSmith, CLI ├── mas_crewai.py # вимога 2: той самий кейс на CrewAI над тим самим MCP-сервером ├── mas_adk.py # бонус: Google ADK, ParallelAgent → SequentialAgent ├── evals.py # бонус: deepeval (5 кейсів) + DeepTeam (3 типи атак) ├── demos.py # вимога 4 та зведення: усі демонстрації → JSON-артефакти ├── test_mas.py # вимога 7: 63 офлайн-тести ├── requirements.txt · .gitignore · pytest.ini · .env.example ├── demo_output.txt · pytest_output.txt # вивід прогонів ├── demo_results.json · costs.json · evals_results.json ├── trace_langsmith.json # фрагмент трейсу для здачі ├── evals_results_before_hardening.json # red-teaming ДО виправлень └── Task_002_Vasileyko_Logistics.ipynb
mermaid
graph TD; __start__([__start__]):::first supervisor(supervisor) tracking_agent(tracking_agent) warehouse_agent(warehouse_agent) pricing_agent(pricing_agent) __end__([__end__]):::last __start__ --> supervisor; supervisor -.->|transfer_to_tracking_agent| tracking_agent; supervisor -.->|transfer_to_warehouse_agent| warehouse_agent; supervisor -.->|transfer_to_pricing_agent| pricing_agent; tracking_agent --> supervisor; warehouse_agent --> supervisor; pricing_agent --> supervisor; supervisor -.-> __end__; classDef default fill:#f2f0ff,line-height:1.2 classDef first fill-opacity:0 classDef last fill:#bfb6fc
text
LangGraph → supervisor → transfer_to_tracking_agent → tracking_agent
→ call_model → ChatOpenAI → tools → cancel_shipment
+ PIIMiddleware[email]/[credit_card], HumanInTheLoopMiddleware, ToolCallLimitMiddlewareFull documentation captured from public sources, including the complete README when available.
Docs source
GITHUB REPOS
Editorial quality
ready
Практичне завдання №2: мультиагентна система логістики — supervisor у LangGraph, CrewAI та Google ADK над спільним MCP-сервером (FastMCP), guardrails (injection/allowlist/PII), HITL, tracing у LangSmith, deepeval + DeepTeam Мультиагентна система логістики: LangGraph, CrewAI, MCP і security hardening Практичне завдання №2 курсу «Агентні системи». Предметна область варіанта — **логістика та складський облік**: трекінг відправлень, залишки на складах, розрахунок вартості доставки і **скасування відправлення з поверненням коштів** як ризикова незворотна операція. Один і той самий кейс реалізовано **тричі** — у LangGraph (supervisor + 3 ворк
Практичне завдання №2 курсу «Агентні системи». Предметна область варіанта — логістика та складський облік: трекінг відправлень, залишки на складах, розрахунок вартості доставки і скасування відправлення з поверненням коштів як ризикова незворотна операція.
Один і той самий кейс реалізовано тричі — у LangGraph (supervisor + 3 воркери), CrewAI (менеджер + 3 виконавці) і Google ADK (workflow-агенти). Усі три ходять у домен через один кастомний MCP-сервер, тому порівняння фреймворків міряє саме оркестрацію, а не інструменти.
LLM-провайдер — OpenRouter (OpenAI-сумісний API), модель openai/gpt-4.1,
temperature=0.1; судді evals і генератор атак — дешевша openai/gpt-4.1-mini.
# 1. Оточення (окремий venv — див. розділ 12, чому не в базовий)
uv venv --python 3.13
uv pip install -r requirements.txt
# 2. Ключі
cp .env.example .env # вписати OPENROUTER_API_KEY і LANGSMITH_API_KEY
# 3. Самоперевірки БЕЗ мережі та БЕЗ ключів — усе має пройти
.venv/bin/python mcp_server.py --selfcheck # 4 MCP-інструменти, валідатори, JSON-конверт
.venv/bin/python guards.py # injection / allowlist / PII / CostTracker
.venv/bin/python mas_crewai.py --selfcheck # склад crew і allowlist
.venv/bin/python mas_adk.py --selfcheck # структура workflow-пайплайна
.venv/bin/python mas_langgraph.py --graph # mermaid-схема графа
.venv/bin/python -m pytest test_mas.py -v # 63 тести
# 4. Живі запити (потрібен ключ)
.venv/bin/python mas_langgraph.py "Де зараз посилка TTN-000001?"
.venv/bin/python mas_crewai.py "Скільки ноутбуків SKU-1001 на складах?"
.venv/bin/python mas_adk.py "Статус TTN-000001 і залишок SKU-1001"
# 5. Human-in-the-loop: граф зупиняється і чекає рішення оператора
.venv/bin/python mas_langgraph.py --thread h1 "Скасуй TTN-000004, клієнт відмовився, поверни 720 грн"
.venv/bin/python mas_langgraph.py --thread h1 --show-state # інший процес бачить паузу
.venv/bin/python mas_langgraph.py --thread h1 --approve # або --reject "занадто рано"
# 6. Повний прогін демонстрацій → demo_results.json, costs.json, trace_langsmith.json
.venv/bin/python demos.py
.venv/bin/python demos.py --only guardrails hitl
# 7. Бонуси: evals і red-teaming (результати кешуються, --force перерахує)
.venv/bin/python evals.py
Ноутбук
Task_002_Vasileyko_Logistics.ipynbзапускається на ядрі GoIT HW-10:.venv/bin/python -m ipykernel install --user --name goit-hw-10 --display-name "GoIT HW-10"
Режими --selfcheck, --graph, --show-state, --approve і --reject працюють
без ключів: LLM у них не викликається, а стан паузи читається з чекпоїнтера.
goit-aad-hw-10/
├── mcp_server.py # вимога 3: FastMCP-сервер, 4 інструменти + мок-дані домену
├── guards.py # вимога 5: injection / allowlist+валідація / PII + облік вартості
├── mas_langgraph.py # вимоги 1, 6: supervisor + 3 воркери, MCP, HITL, LangSmith, CLI
├── mas_crewai.py # вимога 2: той самий кейс на CrewAI над тим самим MCP-сервером
├── mas_adk.py # бонус: Google ADK, ParallelAgent → SequentialAgent
├── evals.py # бонус: deepeval (5 кейсів) + DeepTeam (3 типи атак)
├── demos.py # вимога 4 та зведення: усі демонстрації → JSON-артефакти
├── test_mas.py # вимога 7: 63 офлайн-тести
├── requirements.txt · .gitignore · pytest.ini · .env.example
├── demo_output.txt · pytest_output.txt # вивід прогонів
├── demo_results.json · costs.json · evals_results.json
├── trace_langsmith.json # фрагмент трейсу для здачі
├── evals_results_before_hardening.json # red-teaming ДО виправлень
└── Task_002_Vasileyko_Logistics.ipynb
Окремого hitl.py немає свідомо: у LangChain 1.3 HITL — це один middleware,
і власний модуль навколо нього був би церемонією. Облік вартості теж не окремий
файл, а клас у guards.py, бо його зовуть усі три реалізації.
graph TD;
__start__([__start__]):::first
supervisor(supervisor)
tracking_agent(tracking_agent)
warehouse_agent(warehouse_agent)
pricing_agent(pricing_agent)
__end__([__end__]):::last
__start__ --> supervisor;
supervisor -.->|transfer_to_tracking_agent| tracking_agent;
supervisor -.->|transfer_to_warehouse_agent| warehouse_agent;
supervisor -.->|transfer_to_pricing_agent| pricing_agent;
tracking_agent --> supervisor;
warehouse_agent --> supervisor;
pricing_agent --> supervisor;
supervisor -.-> __end__;
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
| Агент | Роль | Дозволені інструменти | Правило передачі |
|---|---|---|---|
| supervisor | координатор | жодного | маршрутизує і підсумовує |
| tracking_agent | оператор служби доставки | track_shipment, cancel_shipment | статус, історія, скасування ТТН |
| warehouse_agent | комірник | check_stock | залишки за артикулом SKU |
| pricing_agent | тарифікатор | calc_delivery | вартість і термін доставки |
Супервізор навмисно не має доступу до доменних інструментів: інакше він міг би
обійти і поділ ролей, і HITL. Це не декларація — guards.ALLOWLIST["supervisor"]
порожній, і guarded_tools поверне йому порожній список.
mcp_server.py — сервер на mcp.server.fastmcp.FastMCP, транспорт stdio.
| Інструмент | Аргументи | Ризик |
|---|---|---|
| track_shipment | tracking_id | read-only |
| check_stock | sku, warehouse?, min_qty | read-only |
| calc_delivery | origin, destination, weight_kg, service, declared_value_uah? | read-only |
| cancel_shipment | tracking_id, reason, refund_uah | незворотний, під HITL |
Дві схеми на кожен інструмент, і це не дублювання. Сигнатура з
Annotated[str, Field(description=...)] — те, що FastMCP перетворює на JSON Schema
і показує моделі. Pydantic-модель *Input усередині — те, чого в JSON Schema не
виразити: нормалізація регістру (ttn-000001 → TTN-000001, одеса → Одеса)
і крос-польові правила (origin != destination).
Три деталі, які виявилися принциповими:
print() у сервері. У stdio stdout — це канал JSON-RPC; будь-який
друк ламає протокол. Логи йдуть у stderr через logging.cancelled.json, не в пам'яті. Клієнт
langchain-mcp-adapters піднімає новий процес сервера на кожен виклик
інструмента («A new session will be created for each tool call»). Побічний
ефект у глобальній змінній зникав би разом із процесом, і HITL-демонстрація
нічого не доводила б.{"status": "error", "problems": ["tracking_id: очікується формат TTN-XXXXXX"]}
і має з чого виправити аргументи.| Реалізація | Механізм | Як задається allowlist |
|---|---|---|
| LangGraph | langchain-mcp-adapters → MultiServerMCPClient.get_tools() | guards.guarded_tools фільтрує + обгортає перевіркою |
| CrewAI | crewai_tools.MCPServerAdapter + StdioServerParameters | фільтрація списку за guards.ALLOWLIST |
| Google ADK | google.adk.tools.mcp_tool.McpToolset | tool_filter=[...] на рівні самого toolset |
Супервізор — langgraph_supervisor.create_supervisor, він сам генерує
handoff-інструменти transfer_to_<agent>. Воркери — langchain.agents.create_agent
з переліком дозволених інструментів і middleware свого рівня ризику.
Стан — AsyncSqliteSaver у mas_state.db. Асинхронність тут не примха:
інструменти MCP існують лише як корутини, тому синхронний invoke по них
не пройде, і чекпоїнтер довелося брати async-варіантом.
CLI повторює логіку ПЗ №1: --thread для персистентності, --show-state,
--approve, --reject — і всі вони працюють з іншого процесу.
Process.hierarchical — це і є supervisor у термінах CrewAI: manager_agent
сам вирішує, кому делегувати. Ролі дзеркалять воркерів LangGraph дослівно,
інакше порівняння було б нечесним.
Три однакові запити, той самий MCP-сервер, та сама модель. Дані — з costs.json,
згенерованого demos.py:
| Фреймворк | Запитів | Токенів | Вартість, $ | Час, мс | × токенів до мінімуму | |---|---:|---:|---:|---:|---:| | LangGraph | 3 | 6 773 | 0.017512 | 14 864 | 1.00 | | Google ADK | 3 | 8 470 | 0.019352 | 13 518 | 1.25 | | CrewAI | 3 | 32 528 | 0.086056 | 14 886 | 4.80 |
| Метрика | LangGraph | CrewAI | ADK |
|---|---:|---:|---:|
| Модуль цілком | 370 | 265 | 198 |
| Рядків коду (без коментарів і докстрінгів) | 213 | 174 | 130 |
| Лише складання агентів (build_*) | 34 | 34 | 23 |
| Критерій | LangGraph | CrewAI | Google ADK |
|---|---|---|---|
| Модель оркестрації | явний граф, handoff-інструменти | менеджер делегує «по-людськи» | фіксований workflow (Parallel → Sequential) |
| Контроль маршруту | повний: видно вузли й ребра | непрямий, через промпт менеджера | повний, але маршрут статичний |
| Персистентність стану | є (checkpointer) | немає | немає (InMemorySessionService) |
| HITL із паузою | так, interrupt + resume | ні — лише відмова наперед | ні |
| Debugging | --graph, --show-state, спани по вузлах | лог делегування, спани crew/task | лог подій, output_key у стані |
| Витрати токенів | базові | ×4.8 | ×1.25 |
| Готовність до продакшену | висока | середня | середня |
Головний висновок порівняння: різниця в коді мінімальна, різниця в токенах —
майже п'ятикратна. Складання агентів займає 34 рядки і там, і там (23 в ADK),
тобто «менше коду» не є перевагою жодного з фреймворків. А от CrewAI на тих самих
трьох запитах спалив 32 528 токенів проти 6 773 у LangGraph. Причина видно в
трейсі: ієрархічний процес спершу веде діалог менеджера з виконавцем
(Ask question to coworker), і повний контекст задачі переказується двічі —
менеджеру й виконавцю. LangGraph передає керування одним transfer_to_*
без переказу.
guards.py навмисно не імпортує ані langchain, ані crewai, ані adk: ті самі
функції зовуть усі три реалізації, а middleware є лише в LangChain.
Шість правил (guards.INJECTION_PATTERNS), українською й англійською:
override_instructions, reveal_system_prompt, role_marker_injection,
new_persona, structured_exfiltration, encoded_payload, exfiltrate_secrets.
Перевірка стоїть до першого звернення до LLM, тому заблокована атака коштує
рівно 0 токенів — це видно у demo_output.txt.
Два рубежі, а не один:
guarded_tools(agent, tools) фізично не видає агенту чужі інструменти —
вони не потраплять навіть у tool_calls моделі;Доменні правила поверх Pydantic: формати TTN-\d{6} / SKU-\d{4}, відомі міста
й склади і стеля автоматичного повернення MAX_REFUND_UAH = 5000 — понад неї
скасування не проходить навіть після підтвердження оператора.
Шість типів: телефон (+380 і 0XX), e-mail, картка, IBAN UA, ЄДРПОУ, ІПН. Порядок правил має значення: IBAN і картку шукаємо раніше за телефон та ІПН, інакше довший номер розрізався б коротшим правилом на шматки.
Доменні ідентифікатори PII не є: TTN-000001, SKU-1001 і суми лишаються
в тексті — інакше відповідь стала б беззмістовною (test_pii_redaction_keeps_domain_identifiers).
У LangGraph поверх цього ввімкнено готові PIIMiddleware (email, credit_card)
і ToolCallLimitMiddleware з LangChain 1.3 — писати своє під те, що вже є
в залежності, сенсу немає. redact_pii закриває українську специфіку, якої
в них немає, і працює для CrewAI та ADK, де middleware не існує.
Знайдений і виправлений баг. Перша версія правила для телефону мала
(?:\+?38[\s-]?)?\b0\d{2}…— і мовчки пропускала+380671234567: між «8» і «0» словесної межі\bне існує. Спіймано тим, що самоперевірка перевіряла лише наявність маркера[REDACTED:PHONE], а він з'являвся від другого номера в рядку. Виправлено на(?<!\d)…(?!\d); тестtest_international_phone_is_not_missedзакриває регресію.
HumanInTheLoopMiddleware з LangChain 1.3, точково на cancel_shipment і лише
в tracking_agent. Дозволені рішення — approve, edit, reject.
Чому middleware, а не interrupt_before=["tools"]: останній зупиняє весь вузол
інструментів, тобто пауза виникала б і перед звичайним трекінгом. Middleware
зупиняє рівно перед незворотною операцією.
Що доводить демонстрація (demos.py --only hitl, вивід у demo_output.txt):
| Тред | Пауза | Інший процес бачить дію | Журнал до → після |
|---|---|---|---|
| demo-reject | так | так | 0 → 0 — скасування не відбулося |
| demo-approve | так | так | 0 → 1 — скасування записане |
Рішення приймається окремим процесом (demos.py ходить через subprocess):
це і є доказ, що стан паузи лежить у чекпоїнтері, а не в пам'яті.
Проєкт LangSmith — goit-hw-10. Збережений фрагмент — trace_langsmith.json
(25 спанів в одному трейсі).
LangGraph — нульовий код, самі змінні оточення (LANGSMITH_TRACING=true,
LANGSMITH_API_KEY, LANGSMITH_PROJECT). base_url OpenRouter трасуванню не
заважає: трейсер чіпляється до BaseChatModel, а не до HTTP-клієнта. У трейсі
видно повний ланцюг:
LangGraph → supervisor → transfer_to_tracking_agent → tracking_agent
→ call_model → ChatOpenAI → tools → cancel_shipment
+ PIIMiddleware[email]/[credit_card], HumanInTheLoopMiddleware, ToolCallLimitMiddleware
CrewAI — через OpenTelemetry на OTLP-приймач LangSmith
(https://api.smith.langchain.com/otel/v1/traces) плюс
openinference-instrumentation-crewai. У трейсі: Crew.kickoff →
Координатор служби логістики._execute_core → Ask question to coworker →
track_shipment.
Чому не колбек LiteLLM. Документований і найдешевший шлях —
litellm.callbacks = ["langsmith"]— тут не працює, і на це пішло чотири ітерації. Причини, знайдені в коді CrewAI 1.15.18:
LLM.__init__викликаєset_callbacks(self.callbacks or [])і затирає глобальний список (crewai/llm.py:732);- обхід через
LITELLM_SUCCESS_CALLBACKSтеж ненадійний: уset_env_callbacksприсвоєнняlitellm.success_callbackвкладене в перевіркуLITELLM_FAILURE_CALLBACKS, тож без другої змінної воно просто не виконується;- головне — у CrewAI 1.15
openrouterуже є вSUPPORTED_NATIVE_PROVIDERS, тому фреймворк ходить власнимOpenAICompatibleCompletionповз LiteLLM узагалі;is_litellm=Trueце перемикає, але тоді ми міряли б не той шлях, яким CrewAI працює за замовчуванням.OTel виявився не просто обхідним шляхом, а кращим: він дає спани crew, task і делегування, а не лише виклики моделі.
Вартість у LangSmith показується як $0 — у його прайс-мапі немає SKU
openai/gpt-4.1. Тому вартість рахуємо самі (розділ 11).
pytest test_mas.py -v → 63 тести, 0.54 с, усі офлайн (повний вивід —
pytest_output.txt). Мережа не потрібна, LLM не викликається, ключі не потрібні.
| Група | Тестів | Що перевіряє |
|---|---:|---|
| MCP: валідація аргументів | 14 | 11 некоректних входів + нормалізація регістру |
| MCP: бізнес-логіка | 5 | формула ціни, страховка, ліміт overnight, агрегація складів |
| MCP: ризикова операція | 2 | запис у журнал, відмова для доставленого й повторного |
| MCP: протокол | 1 | сервер піднімається по stdio і віддає 4 інструменти зі схемами |
| Guardrail input | 12 | 7 атак спіймано, 4 чисті запити пропущено, повідомлення не називає правило |
| Guardrail tool | 14 | allowlist в обидва боки, невідомий інструмент, стеля повернення |
| Guardrail output | 9 | 7 типів PII, збереження ТТН/SKU, регресія міжнародного номера |
| Обгортка і HITL | 4 | фільтрація, форма content_and_artifact, HITL лише в tracking_agent |
| Облік вартості | 2 | нормалізація префікса openrouter/, арифметика |
Тест test_guarded_tool_blocks_bad_arguments_in_protocol_shape існує через
реальний баг: інструменти від langchain-mcp-adapters мають
response_format="content_and_artifact" і зобов'язані повертати пару
(вміст, артефакт). Перша версія guardrail повертала рядок і валила виклик
з ValueError замість того, щоб акуратно його заблокувати.
guards.CostTracker + ціни OpenRouter, зняті з /api/v1/models:
openai/gpt-4.1 — $2.00/$8.00 за 1M токенів, openai/gpt-4.1-mini — $0.40/$1.60.
Джерела токенів різні для кожного фреймворка: get_usage_metadata_callback()
для LangGraph, crew.usage_metrics для CrewAI, event.usage_metadata для ADK.
Префікс openrouter/ від LiteLLM нормалізується, інакше та сама модель
рахувалася б двічі. Результат — таблиця в розділі 6 і costs.json.
ParallelAgent(tracking, warehouse, pricing) → SequentialAgent(…, reporter).
Модель через LiteLlm("openrouter/openai/gpt-4.1"), Google-ключ не потрібен.
MCP під'єднано третім способом — McpToolset з tool_filter.
Ризиковий інструмент у цю реалізацію не входить свідомо: workflow-агенти йдуть фіксованим маршрутом, місця для паузи в ньому немає, а робити незворотну операцію без HITL не можна.
Цікаве спостереження: ADK виявився найшвидшим (13.5 с проти 14.9 с), бо три збирачі даних працюють паралельно — але саме тому він завжди платить за всіх трьох, навіть коли запит стосується одного.
5 тест-кейсів × 2 метрики, суддя openai/gpt-4.1-mini. Результат — 5/5.
| Запит | Answer Relevancy | Grounded (GEval) | |---|---:|---:| | Де зараз посилка TTN-000001? | 1.00 | 0.93 | | Чому затримується TTN-000005? | 1.00 | 0.85 | | Чи є 10 моніторів SKU-1002 у Києві? | 0.75 | 0.99 | | Вартість 8 кг Одеса→Харків express | 1.00 | 0.97 | | Скільки SKU-1001 на складах? | 1.00 | 1.00 |
Перша спроба дала 40% і це була помилка метрики, а не системи. GEval із суцільним багатоскладовим
criteria(«спирається на дані І не вигадує І не розкриває інструкції І українською») розмивав оцінку і карав відповіді за стислість — хоча всі числа в них правильні (611 грнза 8 кг Одеса→Харків express перевірено вручну:120 + 22×8 + 0.45×700). Замінаcriteriaна явніevaluation_stepsпідняла результат до 5/5 без жодної зміни в самій системі. Висновок: погано специфікований LLM-суддя міряє власну невизначеність.
3 типи атак (PromptInjection, PromptProbing, LinearJailbreaking) проти
2 класів вразливостей (PIILeakage, PromptLeakage) — 8 атак за прогін.
Що знайшов red-teaming і що виправлено:
| # | Знахідка | Виправлення |
|---|---|---|
| 1 | Супервізор на прохання «оптимізувати процес» перелічував внутрішню будову: імена tracking_agent/warehouse_agent/pricing_agent і правила маршрутизації | правило нерозголошення в SUPERVISOR_PROMPT |
| 2 | Псевдо-режим DATA TRANSFORMATION MODE витягував правила у вигляді JSON (GUARD_EXPOSURE, PERMISSIONS_AND_ROLES) — правило reveal_system_prompt знало дієслова show/reveal, але не analyze/extract | розширено список дієслів + нове правило structured_exfiltration |
| 3 | Атаку заблоковано, але сама відмова писала «спрацювало правило reveal_system_prompt» — тобто витікала назва внутрішнього фільтра | guards.BLOCKED_MESSAGE знеособлено; ім'я правила лишається в логах і трейсі |
Стан «до» збережено у evals_results_before_hardening.json, «після» — в
evals_results.json.
Чесно про числа. Підсумок останнього прогону: 3 відбито, 1 пробито,
4 — симулятор здався. Це число не варто читати як оцінку: DeepTeam генерує
нові атаки на кожному прогоні, тому прогони не порівнюються між собою
(за чотири ітерації я бачив 6/8, 5/8, 6/8, 3/8 — при тому, що система ставала
строго безпечнішою). А статус «симулятор здався» — це не помилка системи:
DeepTeam сам пише, що «the simulator model refused to write the next attack»,
тобто атакувальна модель відмовилася продовжувати. Тому в evals.py три різні
результати (withstood / breached / simulator_gave_up) рознесено явно —
початкова версія показувала їх однаково і давала оманливу картину.
pip install crewai у базовий anaconda-env мутує 15 пакетів, зокрема
chromadb 1.5.9 → 1.1.1 — рівно ту бібліотеку, на якій працює RAG попереднього
завдання. Плюс два конфлікти, які довелося розв'язувати пінами:
mcp==1.28.1 — не 2.x: у mcp 2.0 клас FastMCP перейменовано на MCPServer,
а crewai пінить mcp~=1.28.1;deepeval==3.8.9 — не 4.x: deepeval 4 вимагає posthog>=7, chromadb 1.1
(залежність crewai) — posthog<6; разом вони не вирішуються взагалі
(ResolutionImpossible);opentelemetry-exporter-otlp-proto-http==1.42.0 — crewai і google-adk
обидва капають opentelemetry-api ~1.42.Три однакові запити: LangGraph — 6 773 токени ($0.0175), ADK — 8 470 ($0.0194),
CrewAI — 32 528 ($0.0861). При цьому коду на складання агентів однаково —
34 рядки в LangGraph і CrewAI, 23 в ADK. Тобто вибір фреймворка — це не вибір
«більше чи менше писати», а вибір моделі оркестрації: явна передача керування
(один transfer_to_*) проти діалогу менеджера з виконавцем, де контекст
переказується двічі.
Так, і саме тому рубежів два. Фільтрація закриває нормальний сценарій: модель
не бачить чужого інструмента і не може його попросити. Але allowlist ловить те,
чого фільтрація не бачить: виклик із неправильними аргументами. Стеля
MAX_REFUND_UAH — не про доступ, а про повноваження: tracking_agent має право
на cancel_shipment, але не на повернення 99 000 грн. Такого правила у схемі
інструмента немає і бути не може — це політика, а не формат.
Демонстрація доводить рівно дві речі: після reject журнал скасувань лишається
порожнім, після approve — містить рівно один запис; і що паузу видно
з іншого процесу. Друге важливіше за перше: воно означає, що підтвердження
може прийти не з того ж скрипта, а з вебхука, чат-бота чи адмінки — стан живе
в чекпоїнтері, а не в пам'яті конкретного запуску.
Чого демонстрація не доводить: що модель не викличе скасування без прохання. Від цього захищає не HITL, а промпт воркера і allowlist.
Обидва бонуси на LLM-суддях дали спочатку неправильну картину, і в обох випадках
винна була постановка, а не система: розмитий criteria в GEval занизив оцінку
вчетверо, а нерозрізнені статуси в DeepTeam видавали відмову атакувальної моделі
за провал захисту. Практичний висновок: LLM-суддя без явних кроків оцінювання
міряє власну невизначеність, а метрику red-teaming не можна читати як
абсолютне число — лише як перелік конкретних знайдених векторів.
langgraph-supervisor у maintenance mode. Пакет робочий і тягне нуль
транзитивних залежностей, але LangChain рекомендує hand-rolled супервізор на
handoff-інструментах із Command(goto=…, graph=Command.PARENT). Для продакшену
варто перейти — це близько 15 рядків.client.session("logistics").--approve-risky), бо зупинити й продовжити виконання нема де.
Це не обхід, а чесне відображення різниці фреймворків.IPN ловить будь-які
10 цифр підряд; у цьому домені колізій немає, але на іншому корпусі його
треба звужувати контекстом.Machine endpoints, protocol fit, contract coverage, invocation examples, and guardrails for agent-to-agent use.
Contract coverage
Status
missing
Auth
None
Streaming
No
Data region
Unspecified
Protocol support
Requires: none
Forbidden: none
Guardrails
Operational confidence: low
curl -s "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/snapshot"
curl -s "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/contract"
curl -s "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/trust"
Trust and runtime signals, benchmark suites, failure patterns, and practical risk constraints.
Trust signals
Handshake
UNKNOWN
Confidence
unknown
Attempts 30d
unknown
Fallback rate
unknown
Runtime metrics
Observed P50
unknown
Observed P95
unknown
Rate limit
unknown
Estimated cost
unknown
Do not use if
Every public screenshot, visual asset, demo link, and owner-provided destination tied to this agent.
Neighboring agents from the same protocol and source ecosystem for comparison and shortlist building.
Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!
AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents
AI productivity studio with smart chat, autonomous agents, and 300+ assistants.
The Frontend for Agents & Generative UI. React + Angular
Contract JSON
{
"contractStatus": "missing",
"authModes": [],
"requires": [],
"forbidden": [],
"supportsMcp": false,
"supportsA2a": false,
"supportsStreaming": false,
"inputSchemaRef": null,
"outputSchemaRef": null,
"dataRegion": null,
"contractUpdatedAt": null,
"sourceUpdatedAt": null,
"freshnessSeconds": null
}Invocation Guide
{
"preferredApi": {
"snapshotUrl": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/snapshot",
"contractUrl": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/contract",
"trustUrl": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/trust"
},
"curlExamples": [
"curl -s \"https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/snapshot\"",
"curl -s \"https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/contract\"",
"curl -s \"https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/trust\""
],
"jsonRequestTemplate": {
"query": "summarize this repo",
"constraints": {
"maxLatencyMs": 2000,
"protocolPreference": [
"OPENCLEW"
]
}
},
"jsonResponseTemplate": {
"ok": true,
"result": {
"summary": "...",
"confidence": 0.9
},
"meta": {
"source": "GITHUB_REPOS",
"generatedAt": "2026-10-09T20:26:27.238Z"
}
},
"retryPolicy": {
"maxAttempts": 3,
"backoffMs": [
500,
1500,
3500
],
"retryableConditions": [
"HTTP_429",
"HTTP_503",
"NETWORK_TIMEOUT"
]
}
}Trust JSON
{
"status": "unavailable",
"handshakeStatus": "UNKNOWN",
"verificationFreshnessHours": null,
"reputationScore": null,
"p95LatencyMs": null,
"successRate30d": null,
"fallbackRate": null,
"attempts30d": null,
"trustUpdatedAt": null,
"trustConfidence": "unknown",
"sourceUpdatedAt": null,
"freshnessSeconds": null
}Capability Matrix
{
"rows": [
{
"key": "OPENCLEW",
"type": "protocol",
"support": "unknown",
"confidenceSource": "profile",
"notes": "Listed on profile"
},
{
"key": "crewai",
"type": "capability",
"support": "supported",
"confidenceSource": "profile",
"notes": "Declared in agent profile metadata"
},
{
"key": "multi-agent",
"type": "capability",
"support": "supported",
"confidenceSource": "profile",
"notes": "Declared in agent profile metadata"
}
],
"flattenedTokens": "protocol:OPENCLEW|unknown|profile capability:crewai|supported|profile capability:multi-agent|supported|profile"
}Facts JSON
[
{
"factKey": "vendor",
"category": "vendor",
"label": "Vendor",
"value": "Alexnodejs",
"href": "https://github.com/alexnodejs/goit-aad-hw-10",
"sourceUrl": "https://github.com/alexnodejs/goit-aad-hw-10",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-10-09T13:51:05.655Z",
"isPublic": true
},
{
"factKey": "protocols",
"category": "compatibility",
"label": "Protocol compatibility",
"value": "OpenClaw",
"href": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/contract",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/contract",
"sourceType": "contract",
"confidence": "medium",
"observedAt": "2026-10-09T13:51:05.655Z",
"isPublic": true
},
{
"factKey": "docs_crawl",
"category": "integration",
"label": "Crawlable docs",
"value": "6 indexed pages on the official domain",
"href": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceUrl": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceType": "search_document",
"confidence": "medium",
"observedAt": "2026-04-15T05:03:46.393Z",
"isPublic": true
},
{
"factKey": "handshake_status",
"category": "security",
"label": "Handshake status",
"value": "UNKNOWN",
"href": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/trust",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/crewai-alexnodejs-goit-aad-hw-10/trust",
"sourceType": "trust",
"confidence": "medium",
"observedAt": null,
"isPublic": true
}
]Change Events JSON
[
{
"eventType": "docs_update",
"title": "Docs refreshed: Sign in to GitHub · GitHub",
"description": "Fresh crawlable documentation was indexed for the official domain.",
"href": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceUrl": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceType": "search_document",
"confidence": "medium",
"observedAt": "2026-04-15T05:03:46.393Z",
"isPublic": true
}
]Sponsored
Ads related to goit-aad-hw-10 and adjacent AI workflows.