Commit Graph

2644 Commits

Author SHA1 Message Date
Lucas Gomide
3444a2c190 fix: dedupe tool_selection and honor payload on catalog seams
Addresses review findings on the remaining interception points. `TOOL_SELECTION`
is no longer dispatched in `Crew._prepare_tools`; the single dispatch in
`Agent.create_agent_executor` covers both crew and standalone runs, so hooks no
longer fire twice (and additive edits no longer duplicate tools). `PRE_DELEGATION`
now dispatches outside the delegation `try/except`, so a `HookAborted` propagates
instead of being swallowed into a tool-error string. The `PRE_STEP` (flow),
`PRE_CODE_EXECUTION`, and `MCP_CONNECT` seams now apply the returned payload:
flow step params are rebound onto the call, script code is recompiled from the
edited source, and the MCP transport is replaced before connecting.
2026-07-11 19:25:37 -03:00
Lucas Gomide
fc906c8233 feat: wire remaining interception points and document the catalog
Wires the step, agent, subsystem, and flow points onto the dispatcher:
`pre_step`/`post_step`, `tool_selection`, `pre_delegation`, `retry_attempt`,
`memory_write`/`memory_read`, `knowledge_retrieval`, `pre_code_execution`,
`mcp_connect`, `flow_transition`, and `router_decision`, extending the typed-
context module with their contexts. Each seam passes a typed context whose
`payload` a hook may observe, mutate, or replace. Adds the conformance suite
for these points and a new `interception-hooks` doc page with the full
point/payload catalog and the interceptor contract.
2026-07-11 19:20:17 -03:00
Lucas Gomide
73bdfaad56 fix: correct execution-boundary hook ordering and input aliasing
Reworks the crew and flow boundary seams flagged in review. `OUTPUT` and
`EXECUTION_END` now run before the completion event (`CrewKickoffCompletedEvent`
and `FlowFinishedEvent`) so a `HookAborted` no longer leaves a spurious
completed signal and a returned payload replacement is honored on the emitted
and returned result. Boundary contexts alias `inputs` to the same object as
`payload` instead of a fresh dict from `or`, so in-place edits survive
read-back. Flows re-publish the resolved inputs into `flow_inputs` baggage
after the `INPUT` hook so trigger-payload injection observes hook rewrites, and
a resumed flow now dispatches `OUTPUT`/`EXECUTION_END` on its completion path.
2026-07-11 19:20:03 -03:00
Lucas Gomide
10b6b9f948 feat: wire execution-boundary interception points
Adds the typed interception contexts (`crewai/hooks/contexts.py`) and wires
the `execution_start`, `input`, `output`, and `execution_end` points for both
crews and flows through the dispatcher. `prepare_kickoff` and
`Flow.kickoff_async` fire `execution_start`/`input` so a hook can rewrite
resolved inputs before the run, while `Crew._create_crew_output` and the flow
tail fire `output`/`execution_end` so the final result can be observed or
replaced. Closes the eight critical-path points without touching the legacy
hooks.
2026-07-11 19:12:30 -03:00
Lucas Gomide
f7bd240499 fix: harden interception dispatcher against review findings
Corrects several dispatcher edge cases surfaced in review. `_default_reducer`
now reports a modification only when a `payload` is actually applied, the
`agents=` filter falls back to `agent_role` for contexts without an `agent`
object, and `unregister` resolves the filter wrapper stashed by `on` so a
filtered hook can be removed. The tool-hook runners honor the executing
agent's `verbose` flag instead of silently swallowing hook errors, and the
ReAct tool path now runs `POST_TOOL_CALL` on blocked calls to match the
native paths. Also adds abort-telemetry coverage and replaces the flaky
absolute no-op timing budget with a relative one.
2026-07-11 19:12:15 -03:00
Lucas Gomide
a85e100bec feat: add generic interception-hook dispatcher
Introduces `crewai/hooks/dispatch.py` as a single engine behind every
interception point: a hook receives a typed context, may mutate or replace
its `payload`, or raise `HookAborted(reason, source)` to stop the operation.
The full `InterceptionPoint` catalog is frozen from day zero, with global and
contextvar-scoped registries, an `@on` decorator, a no-op fast path, and a
`HookDispatchedEvent` for telemetry. The four existing `before/after_llm_call`
and `before/after_tool_call` hooks become adapters over the dispatcher, so the
legacy dialect and `return False` semantics keep working unchanged while
gaining the new contract.
2026-07-11 14:14:39 -03:00
João Moura
fb8e93be25 fix(flow): don't double-append the turn reply when a handler trims history (#6510)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
handle_turn() (and stream_turn) decided "did the handler append its
reply?" by snapshotting the assistant-message count before kickoff and
appending the stringified result when the count came back unchanged. A
handler that appends its reply and then trims state.messages to a cap —
a normal bounded-context pattern — left the count unchanged, so the
fallback appended the reply a second time on every turn once trimming
engaged, and the duplicates then crowded real turns out of the capped
window.

Replace the count heuristic with an explicit per-turn flag:
append_assistant_message() sets _assistant_reply_appended, handle_turn
and stream_turn clear it before kickoff and only fall back when no
assistant message was appended during the turn. The now-unused
_assistant_message_count() helper is removed.

Fixes EPD-181.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 20:01:07 -07:00
João Moura
4fdb7f2bfb fix(tools)!: make tool-result caching opt-in instead of on by default (#6509)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
* fix(tools)!: make tool-result caching opt-in instead of on by default

Tool-result caching defaulted to on (Crew.cache=True, and standalone
agents self-wired a CacheHandler at construction), so an LLM calling
the same tool with identical arguments twice in one run silently got
the first result back without the tool executing. For live-data tools
that is a confidently stale answer; for state-mutating tools the second
action is silently dropped.

Caching is now opt-in with the machinery unchanged:
- Crew.cache defaults to False; Crew(cache=True) restores today's
  behavior exactly (agents still default to participating when a crew
  offers its handler, and Agent(cache=False) still opts an agent out).
- Standalone agents no longer self-wire a cache; Agent(cache=True) or
  an explicit cache_handler opts in. Previously even Crew(cache=False)
  agents cached via this self-wired handler.
- Per-tool cache_function write gating is unchanged once opted in.

Existing tests that exercised the caching machinery now opt in
explicitly; new regression tests cover the default (both identical
calls execute), crew-level opt-in dedup, and agent-level wiring.

Fixes EPD-180.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): don't let copy() turn the cache default into an explicit opt-in

Agent.copy() rebuilds from model_dump(), which includes the field
default cache=True, so the copy's model_fields_set contained "cache"
and _setup_agent_executor wired a CacheHandler the source agent never
opted into (Bugbot review finding). Drop "cache" from the dump when it
was not explicitly set on the source; explicit opt-ins still survive
copying.

Also sync the Crew and BaseAgent class docstrings with the new opt-in
cache semantics (CodeRabbit review findings).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): preserve cache_handler-only opt-in across Agent.copy()

copy() excludes cache_handler from the rebuilt agent, so an agent that
opted into tool-result caching solely via an explicit cache_handler
lost caching after copy() (Bugbot review finding). Carry the consent as
cache=True on the copy when the source has a handler wired and hasn't
explicitly disabled caching — the copy wires its own fresh handler,
matching pre-change copy semantics (copies never shared the source's
handler instance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(crew): offer the crew cache handler to the hierarchical manager

The hierarchical manager agent is created in _create_manager_agent,
outside the validation-time agents loop that offers the crew's cache
handler — and managers no longer self-wire a handler — so
Crew(cache=True) hierarchical runs never cached the manager's
delegation tool calls (Bugbot review finding). Offer the shared crew
handler when the crew opted in; a user-provided manager with
cache=False stays excluded via the existing set_cache_handler gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): only construction-time cache opt-ins survive Agent.copy()

The previous copy() fix treated any wired cache_handler as consent, but
agents that merely received the crew's shared handler at kickoff
(set_cache_handler from Crew(cache=True)) never opted in themselves —
their copies must not become standalone cachers (Bugbot review
finding). Record the opt-in signal in _setup_agent_executor, which runs
at construction before any crew wiring can happen, and have copy()
consult that flag instead of inspecting cache_handler after the fact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:37:36 -07:00
João Moura
bfa652a7be fix(tools): stop rewriting the authored tool description at construction (#6508)
* fix(tools): stop rewriting the authored tool description at construction

BaseTool.model_post_init silently replaced the public description field
with the LLM-facing composite ("Tool Name: ...\nTool Arguments: ...\n
Tool Description: <authored>"), breaking equality assertions on authored
text and hiding the extra prompt tokens from token-careful authors.

The authored description now survives construction as written. The
composite is composed on demand via a new formatted_description property
on BaseTool and CrewStructuredTool (shared format_description_for_llm
helper), and every prompt path that relied on the baked-in composite —
render_text_description_and_args, ToolUsage._render, and tool-usage
error messages — now renders through it, so the text the LLM sees is
unchanged.

The helper strips any pre-existing composite block before composing, so
tools deserialized from old checkpoints and adapters that still bake the
composite into the field (e.g. the crewai-tools MCP adapter) don't get
double-wrapped. BaseTool._generate_description remains as a no-op hook
because subclasses override it and model_post_init still calls it.

Fixes EPD-179.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(tools): harden composite-description handling after review

- Anchor the pre-baked-composite check to the actual three-line block
  shape instead of a naive substring match, so authored prose that
  merely mentions "Tool Description:" is never truncated (CodeRabbit /
  Bugbot review finding). Shared as
  strip_composite_description_prefix() and reused by the function-
  calling schema builder, which had the same naive split.
- Make render_text_description_and_args tolerate duck-typed tools
  without a real formatted_description string (fixes CI: step-executor
  tests pass Mock tools whose auto-created attribute is not a str).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-07-10 20:33:57 -03:00
João Moura
b65c8487d2 fix(output): expose token usage under both names on agent and crew results (#6507)
Agent.kickoff() returned LiteAgentOutput with a plain dict at
.usage_metrics and no token_usage attribute, while Crew.kickoff()
returned CrewOutput with a UsageMetrics object at .token_usage and no
usage_metrics attribute — so a usage accessor written for one path
raised AttributeError on the other, and every consumer had to
duck-type both shapes.

Give both result types both surfaces, each name with one consistent
shape everywhere: .token_usage is a UsageMetrics object and
.usage_metrics is a plain dict, on both LiteAgentOutput and CrewOutput.
Added as read-only properties, so existing fields, serialization, and
constructors are unchanged.

Fixes EPD-178.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 20:29:34 -03:00
João Moura
a8b3ecb723 fix(agent): report per-call usage metrics on kickoff results (#6506)
* fix(agent): report per-call usage metrics on kickoff results

Agent.kickoff() populated result.usage_metrics from the LLM instance's
lifetime token accumulator, so counts grew across calls and pooled
across agents sharing one LLM object — a second agent's first turn
appeared to cost the whole preceding session.

Snapshot the accumulator when a kickoff starts and report the delta on
the result (guardrail retries included), via the new
UsageMetrics.delta_since(). The LLM instance's cumulative counters are
untouched: get_token_usage_summary() keeps lifetime totals for
crew-level aggregation, and its docstring now states that scope
explicitly. Applies to both Agent and the deprecated LiteAgent, sync
and async paths.

Fixes EPD-177.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(agent): drop lite_agent.py diff, add guardrail-retry usage test

Per review: LiteAgent's kickoff path is no longer used, so the per-call
usage snapshot only needs to live in agent/core.py — revert the
lite_agent.py changes entirely. This also removes the duplicated
_current_usage_summary helper and the instance-attr baseline CodeRabbit
flagged.

Add the requested guardrail-retry regression test: a guardrail that
rejects the first attempt and accepts the second must yield
usage_metrics covering both attempts (2x a single-attempt kickoff).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 14:17:45 -07:00
João Moura
7967b19057 fix(flow): stop replaying previous turn's intent when route_turn() returns falsy (#6505)
In conversational flows, a falsy return from an overridden route_turn()
fell back to the sticky state.last_intent from a previous turn, silently
re-running the prior turn's handler for an unhandled input.

The fallback exists for the legacy default_intents path, where
receive_user_message() classifies the intent fresh each turn. Track that
per-turn classification in _turn_classified_intent (cleared on every turn
reset) and route on it instead, so a falsy route_turn() now falls through
to the built-in answer_from_history/converse defaults and never reuses
stale routing state.

Fixes EPD-176.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-07-10 11:44:57 -07:00
João Moura
85c467dfe2 feat(cli): run declarative flows on the TUI (headless terminal fallback) (#6484)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
* feat(cli): run declarative flows on the TUI with a headless terminal fallback

Declarative flows now run on the CrewRunApp TUI when interactive, matching
declarative crews and conversational flows. Headless contexts — CREWAI_DMN
(deploy), piped output, CI, any non-TTY — fall back to the direct-terminal
kickoff, gated by is_interactive() (folds in the CREWAI_DMN check and requires
a real TTY).

The TUI shows per-method progress: a new STEPS panel driven by flow method
events (FlowStarted / MethodExecutionStarted/Finished/Failed), each labeled
with its declarative call type (crew/agent/expression/…) read from the flow
definition. Crews/agents inside a method keep streaming in the main panel via
the existing crew/task/LLM handlers.

- crew_run_tui.py: _run_flow_worker (flow.kickoff in a thread worker; reuses
  _on_crew_done/_on_crew_failed + _stringify_output), _is_flow_run gate so crew
  rendering is byte-identical, flow-event subscriptions building _flow_steps,
  and the STEPS sidebar + flow-aware header.
- run_declarative_flow.py: is_interactive() branch → _run_declarative_flow_tui
  (EventListener, method-type map from flow._definition, crew-parity exit codes
  and deploy chaining) or the existing terminal path.

Deviation from the approved plan: gate on is_interactive() rather than
is_dmn_mode_enabled() alone, so non-TTY runs (CI/pipes/CliRunner) never launch
a TUI — this also keeps existing headless flow tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): force flow events on for the TUI so STEPS renders under suppress_flow_events

Review follow-up: the STEPS panel and header are driven by flow method events
(FlowStarted / MethodExecution*), but the declarative runtime skips emitting
those when the flow declared config.suppress_flow_events. Interactive TUI runs
would then keep STEPS on "waiting…" and the header on "Starting flow…" while
nested crews still execute.

_run_declarative_flow_tui now forces flow.suppress_flow_events = False for the
interactive run (mirroring how the conversational path mutates the flow for the
TUI). The headless/terminal path never reaches this and keeps the flow's
declared setting. Regression test: test_run_declarative_flow_tui_enables_flow_events.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): clear flow header's current method when a method ends

Review follow-up: the flow header keys off _current_method, which was set on
MethodExecutionStarted but never cleared on Finished/Failed. Between steps (or
after a failed method before kickoff exits) the header kept spinning the old
method name while the STEPS sidebar already showed it done/failed.

_clear_current_method now drops the header's active method when it ends,
falling back to another still-active step (methods can overlap) or none. The
header's idle fallback shows "Working…" once a step has run and "Starting
flow…" only before the first method.

Tests: test_current_method_clears_and_falls_back_across_overlap, plus a
_current_method assertion in test_flow_method_events_build_steps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix: suppress flow console panels in TUI mode; clear header agent on method change

Two review follow-ups:

1) Method panels break Textual TUI (Cursor): forcing suppress_flow_events off
   so the STEPS panel receives events also un-gated the EventListener's Rich
   flow/method panels (ConsoleFormatter.print_panel prints is_flow=True panels
   regardless of verbose), which interleave with Textual and corrupt the TUI.
   print_panel now skips is_flow panels when is_tui_mode() is set (the same
   context the TUI worker already establishes and the tracing listeners already
   honor). Non-TUI/headless flow runs are unaffected. Test:
   test_console_formatter_tui_mode.

2) Flow header showed a stale agent (CodeRabbit): _current_agent persisted
   across methods. It's now cleared when a method starts and when the active
   method changes, so the header never shows the previous method's agent until
   a new agent event arrives. Test: test_flow_method_transitions_clear_current_agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): keep flow name over nested crews; show paused flow methods

Two review follow-ups on the flow TUI:

1) Crew kickoff renamed the flow (Cursor): CrewKickoffStartedEvent overwrote
   _crew_name / the app title with a nested `call: crew` step's crew name, so
   the post-run summary could be labeled with a child crew. The rename is now
   gated on `not _is_flow_run`, preserving the flow's name; crew runs still
   adopt the crew name. Tests: test_crew_kickoff_does_not_rename_flow_run,
   test_crew_kickoff_renames_in_crew_mode.

2) Paused methods showed active (Cursor): the TUI didn't handle
   MethodExecutionPausedEvent, so a @human_feedback pause left the STEPS
   spinner running (flow status panels are suppressed in TUI mode). It now
   marks the step "paused" (⏸, teal) and the header shows "waiting for
   feedback" instead of a spinner. Test: test_method_paused_marks_step_paused.

Note: interactively *providing* human feedback from the flow TUI is a separate
follow-up; this only makes the pause visible instead of a silent stuck spinner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): run human-feedback declarative flows on the terminal, not the TUI

Two review follow-ups, both rooted in @human_feedback methods:

- Paused flow marked complete (Cursor): async human feedback makes kickoff
  RETURN a HumanFeedbackPending marker (not raise), which _run_flow_worker
  would stringify and report as a successful completion with exit 0.
- Sync feedback breaks TUI (Cursor): default (sync) @human_feedback collects
  input via the flow runtime's Rich console.print + blocking input(), which
  interleaves with Textual and leaves the user unable to review output or
  submit feedback.

run_declarative_flow now routes any flow whose declarative definition declares
human feedback (_flow_uses_human_feedback) to the terminal path, where blocking
input and Rich prompts work natively — regardless of interactivity. Non-feedback
flows still get the TUI. Tests: test_flow_uses_human_feedback_detection,
test_human_feedback_flow_uses_terminal_even_when_interactive.

Fully interactive human feedback inside the TUI remains a separate follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* refactor(cli): address review — Flow typing, debug logging, flow-vs-crew naming

Review follow-ups from @lucasgomide:

- Type flow helpers as Flow[Any] (via TYPE_CHECKING import) instead of Any and
  drop the defensive getattr chains — _definition is a typed PrivateAttr and
  name/suppress_flow_events are typed fields, so attribute access is safe.
- Replace the silent `except Exception: pass` blocks with logger.debug(...,
  exc_info=True) so unexpected failures are diagnosable in the field
  (_flow_method_types, _flow_uses_human_feedback, suppress_flow_events toggle).
- Flow-vs-crew naming: the flow worker now uses group="flow" (was the
  misleading "crew"), and the shared completion/failure handlers report the
  run with an entity-aware noun ("flow" vs "crew") via _run_noun.

Deferred (separate PR): the os._exit(130) hard-kill on user quit is kept as-is
to match the existing crew convention (run_crew._run_json_crew).

Tests: test_flow_done_uses_flow_wording_for_unfinished_tool; existing crew
wording tests unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 11:42:12 -03:00
Lorenze Jay
7baf8f9ba1 improving custom OpenAI urls (#6490)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
* Support legacy OpenAI base URL env var

* Add custom OpenAI-compatible endpoint support

* Refactor OpenAI completion module test to restore original module state

- Added logic to save and restore the original OpenAI completion module during the test to prevent issues with class re-imports affecting subsequent tests.
- Ensured that the test checks for the presence of the module and its attributes only after the module is properly reloaded.
- Improved test reliability by avoiding potential failures due to module state changes across tests.

* addressing comments
2026-07-09 15:30:16 -07:00
Lucas Gomide
860817cbcd Drain memory writes before kickoff and flow completion events (#6497)
* fix: drain memory writes before kickoff and flow completion events

Background memory saves from the final task could still be in flight
when `CrewKickoffCompletedEvent`/`FlowFinishedEvent` fired, so telemetry
listeners tore down before `MemorySaveCompletedEvent` arrived and the
save span surfaced as "Span orphaned" errors in traces despite the
record persisting. `Crew` now drains all pending saves — including
per-agent `agent.memory` pools, which the old `finally`-only drain
missed entirely — before emitting the completion event, with the same
ordering applied to both `FlowFinishedEvent` emit paths in the flow
runtime.

* fix: address review findings on the memory drain paths

Bugbot and CodeRabbit flagged gaps in the drain coverage: the
hierarchical `manager_agent` memory pool was never drained,
`Crew.akickoff` lacked the exception-path safety net that sync
`kickoff` has, and `finalize_session_traces` emitted the deferred
session-end `FlowFinishedEvent` without draining first. Also offloads
the pre-emit drains in the flow runtime to `asyncio.to_thread` so the
blocking wait doesn't stall other coroutines sharing the event loop.

* fix: flush event bus after memory drain in flow completion paths

Bugbot flagged that flow paths went straight from the memory drain to
`FlowFinishedEvent`, while crew kickoff flushes the bus in between.
Save completion events emitted during the drain could still have
pending async handlers when flow-finished triggered trace teardown.
Adds a `crewai_event_bus.flush()` after the drain at both flow runtime
emit sites and in `finalize_session_traces`, mirroring
`Crew._create_crew_output`.
2026-07-09 15:01:14 -04:00
Lorenze Jay
289686ab49 [docs-freeze] docs: snapshot and changelog for v1.15.2 (#6479)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
1.15.2
2026-07-07 19:05:05 -07:00
Lorenze Jay
589baa3e7f feat: bump versions to 1.15.2 (#6477) 2026-07-07 18:59:59 -07:00
João Moura
835b93d8c8 fix(cli): key model-catalog cache by exact API key, shorten TTL, skip Ollama (#6468)
Follow-ups to #6462's caching:

1. Key the catalog cache by the exact API key (via a short, non-reversible
   sha256 digest — never the key itself), not just key-present vs absent.
   Switching to a different key for the same provider now misses the previous
   account's entry and refetches, instead of showing the old account's models.

2. Never cache local providers (Ollama). /api/tags is fast and installed
   models change out-of-band, so caching could keep offering a model the user
   just deleted until the entry expired. _is_cacheable() gates both cache read
   and write; the picker now re-probes every call and reflects what's installed.

3. Shorten the dynamic catalog TTL from 6h to 5m — a stale list (new/removed
   models, account changes) is worse than a ~1s refetch, and the cache only
   needs to spare repeated fetches within a wizard session.

Tests: distinct-key cache entries, digest never stores the raw key, Ollama not
cached (reflects deletions / never written), and dynamic TTL expiry.


Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 18:47:19 -07:00
João Moura
3246cb30f5 fix(cli): unify crewai run flow input resolution and prompt from the state schema (#6466)
* fix(cli): unify `crewai run` flow input resolution; prompt from state schema

`crewai run` resolved the configured [tool.crewai] flow, but `--inputs` was
hard-gated behind `--definition` and routed through a separate branch — the two
ways of pointing at the same flow didn't share resolution, and required inputs
were never detected, prompted, or validated (a missing field only blew up at
runtime).

Now inputs and definition come from one place:

- Remove the "--inputs requires --definition" gate (cli.py, run_crew.py,
  run_declarative_flow.py). `--inputs` alone resolves the configured flow,
  exactly like a bare `crewai run`; `--definition` is purely an override. The
  project-env re-exec forwards `--inputs` instead of rejecting it.
- Read the flow's state schema from the runtime Flow instance
  (`type(flow.state).model_json_schema()`), which is reliable for both inline
  `json_schema` and ref-imported `pydantic` state (the static definition's
  json_schema is None for the common ref case).
- Plain `crewai run` detects required state fields (minus those satisfied by
  state defaults) and prompts for them interactively, showing each field's
  description; skipped in non-interactive / CREWAI_DMN mode.
- Validate against the schema before kickoff: pointed
  "Missing required input 'x' — <description>" errors, and warn on unknown keys
  with a did-you-mean suggestion (catches typos like `prospect_emai`).

`--inputs` on a non-flow project now errors clearly ("only supported for
declarative flows") instead of the old confusing gate.

Tests: schema-driven prompt/validate/override paths, unknown-key warning,
defaults-satisfy-required, type validation, and re-exec input forwarding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): forward reserved `id` input to flow kickoff; ruff format

- Cursor: the schema filter treated an `id` key in --inputs as unknown and
  dropped it, regressing kickoff's persistence-restore support (inputs["id"]).
  Let `id` pass through untouched (test: reserved_id_input_is_forwarded).
- Apply ruff format to run_declarative_flow.py (fixes the lint-run
  `ruff format --check` step).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): don't block persistence-restore resume on schema validation

Cursor (High): `crewai run --inputs '{"id":"…"}'` is a persistence resume —
kickoff hydrates full state from storage, so schema-required fields may come
from the restored state rather than --inputs. The new required-field
prompt/validation was erroring/prompting before kickoff, breaking resume. When
`id` is present in --inputs, forward the inputs unchanged and skip the
prompt/validation. Test: test_id_only_input_skips_required_validation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): load project .env in the declarative-flow runner

The declarative-flow path never loaded .env — flow projects (type = "flow")
missed API keys/config that crew projects pick up. The JSON-crew path loads
Path.cwd()/.env with override=True (run_crew._run_json_crew); mirror that at
the top of run_declarative_flow() so flow projects behave the same regardless
of where crewai is installed. Test: run_declarative_flow_loads_project_env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* feat(cli): unify runtime-input prompting across declarative flows and crews

Declarative (JSON) crews now resolve inputs the same way declarative flows
do, via a shared crewai_cli.input_prompt module (prompt_for_inputs,
parse_inputs_json, closest_name, is_interactive):

- accept --inputs (previously rejected for crews), forwarded to the crew
  subprocess via CREWAI_JSON_CREW_INPUTS and validated before spinning up uv
- layer --inputs over the crew's declared `inputs` defaults
- prompt for missing {placeholder}s with the same UX as flows, and error
  cleanly with a pointed per-name message when non-interactive
- warn on unknown keys with a "did you mean" suggestion

Unlike flows — whose state schema is authoritative, so unknown keys are
dropped — the crew placeholder scan is heuristic (agent/task text fields
only), so unrecognized keys are warned about but kept, to avoid discarding a
value a field the scan doesn't cover may rely on.

--inputs remains rejected for classic (Python/YAML) crews, which take their
inputs from main.py. run_declarative_flow's private input helpers move to the
shared module with no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* test(crewai): update mirrored CLI test after run_crew input refactor

lib/crewai/tests/cli/test_run_crew.py imports crewai_cli internals and is
collected by the lib/crewai test job (Run Tests). It still imported
_prompt_for_missing_inputs, which was replaced by _resolve_crew_inputs, so
the module failed to import — erroring pytest at collection and cancelling
the rest of the matrix via fail-fast.

Point it at _resolve_crew_inputs and patch the prompt in the shared
crewai_cli.input_prompt module where prompting now lives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): filter unknown --inputs keys even on flow persistence restore

Review follow-up: the `id` (persistence-restore) branch of
_resolve_flow_inputs returned the raw payload, so typo keys passed alongside
`id` skipped the unknown-key warning/drop and reached kickoff — which can
fail strict (extra="forbid") flow state models. The restore path now still
warns on and drops unknown keys (keeping `id` and known state fields); it
only skips the required-field prompt and pre-kickoff validation, which
persistence hydrates. Regression test: test_id_restore_still_drops_unknown_keys.

Also drop the duplicate module import in test_input_prompt.py (both `import`
and `from ... import` of crewai_cli.input_prompt) flagged by the code-quality
bot; monkeypatching now uses the string target form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:17:09 -03:00
Renato Nitta
fc41c42773 docs: update language from Rules to Policies to match the new dashboard changes (#6471)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
* docs: rename ACP rules to policies across edge and v1.15.1 locales with redirects

* docs: point ACP policies pages at the new policy screenshots

* docs: address review — revert frozen v1.15.1 edits and fix redirect ordering

* docs: prefix edge policies cross-links so they resolve until the next version cut

* docs: move policies redirects above all wildcard redirects
2026-07-07 15:43:51 -03:00
Renato Nitta
792b58f46b fix: resolve pip-audit failures (onnx 1.22.0, nltk PYSEC-2026-597) (#6472)
* fix: upgrade onnx to 1.22.0 and ignore unfixed nltk advisory in pip-audit

* fix: sync pip-audit ignore list in pre-commit config with the workflow
2026-07-07 14:09:19 -03:00
Lorenze Jay
799ab0f548 ensure we are writing version for flows (#6467)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-07-06 18:47:27 -07:00
João Moura
2b56dab813 feat(cli): pull latest LLM models dynamically in the crew wizard (#6462)
* feat(cli): pull latest LLM models dynamically in the crew wizard

The JSON-crew creation wizard hardcoded a short model list per provider,
which goes stale as vendors ship new models every few weeks. Add a
three-tier resolver that prefers live data and falls back to a curated list.

- New `model_catalog.get_provider_models(provider, fallback)`:
  1. Vendor API (openai/anthropic/gemini/groq/cerebras/ollama) when the
     provider key is already in the environment — the only reliably-fresh
     source (real release dates / display names).
  2. Curated hardcoded fallback — hand-verified, used when no key is set.
  3. LiteLLM feed — only for providers with no curated list; it lags real
     releases, so it must never preempt the curated fallback.
- Rank by date/version parsed from model ids, humanize labels, 6h cache,
  short timeouts, silent fallback on any error.
- Wire it into `create_json_crew._select_model()` (picker only).
- Refresh the curated fallback against each vendor's official model docs
  (Anthropic Fable 5 / Opus 4.8 / Sonnet 5; OpenAI GPT-5.5(+pro); Gemini
  3.5 Flash / 3.1 Pro preview / 3 Flash preview; Groq Llama 4 / GPT-OSS).
- Tests for ranking, chat filtering, caching, and the tier order (17 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): address model_catalog review findings

- Key the Ollama catalog cache by its base URL so a changed OLLAMA_API_BASE /
  API_BASE no longer serves the previous host's models for up to the TTL.
- Negatively cache the curated fallback after a failed/empty fetch (short
  _NEGATIVE_TTL) so the picker doesn't repeat a timeout-prone vendor/LiteLLM
  request on every call — most impactful for a down local Ollama server.
- Guard _read_catalog_cache / _write_catalog_cache against a non-dict cache
  root (corrupt JSON array no longer raises AttributeError).
- Replace the two empty `except OSError: pass` blocks with
  contextlib.suppress(OSError) plus an explanatory comment (CodeQL empty-except).
- Tests: negative cache, base-keyed Ollama cache, corrupt-cache no-crash (20 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): guard null litellm_provider and paginate Gemini models

- _from_litellm: coerce a present-but-null `litellm_provider` before string
  ops so it's skipped instead of raising AttributeError (keeps the documented
  "never raises" contract).
- _fetch_gemini: walk models.list pages via nextPageToken (bounded to 10) —
  the API is paginated and not guaranteed newest-first, so a single page could
  drop models the ranking should consider.
- Tests for both (22 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* ci: ignore nltk PYSEC-2026-597 in pip-audit (no fix, not reachable)

pip-audit newly flags nltk 3.9.4 for PYSEC-2026-597 (CVE-2026-12243), a path
traversal via percent-encoded `..%2f` in nltk.data.load()/find(). It affects
all nltk versions <=3.9.4 with no patched release, so it can't be resolved by a
version bump — same situation as the already-ignored PYSEC-2026-97.

nltk is a transitive dependency (unstructured[local-inference, all-docs] in
crewai-tools) used for text tokenization; we never pass untrusted resource
URLs/paths to nltk.data, so the traversal is not reachable. Add it to the
curated --ignore-vuln list with a justification, matching the existing pattern.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): address second Cursor review round on model_catalog

- Cache ignores new API keys: include API-key presence in the cache key
  (`<provider>#key|#nokey`), so a key added after a no-key/negative-cached
  lookup triggers a fresh live fetch instead of serving the stale fallback.
- Bad LiteLLM cache crashes picker: `_from_litellm` now requires a dict from
  `_load_litellm_data` (a non-mapping JSON root is skipped, not `.items()`'d).
- Stale LiteLLM refetch loop: memoize the feed load once per process
  (`_litellm_memo` + `_reset_litellm_memo` test hook) so repeated uncurated-
  provider lookups don't each re-attempt a timed download when offline.
- Tests: new-key bypass, corrupt-litellm-cache no-crash, one-fetch-per-process
  (25 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): keep partial Gemini results on later-page fetch error

_fetch_gemini paginates; a network/HTTP error on page 2+ previously raised out
through _from_vendor, discarding models already parsed from earlier pages and
forcing the curated fallback. Catch per-page fetch errors and return the
partial set instead (a first-page failure still yields an empty list -> fallback).
Test: test_vendor_gemini_keeps_partial_on_later_page_error (26 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): don't let an invalid fresh LiteLLM cache block download

_fetch_litellm_data treated any truthy JSON root in a fresh provider_cache.json
as the feed and returned it, so a non-mapping root (e.g. a JSON array) was
memoized and the tier never re-downloaded until the file aged out — leaving
uncurated providers with an empty picker despite a recoverable cache. Only
short-circuit on a usable dict; otherwise fall through to the download.
Test renamed to test_invalid_litellm_cache_falls_through_to_download (asserts
recovery via refetch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): honor OLLAMA_HOST and treat empty vendor list as authoritative

- Ollama host mismatch: _ollama_base now also reads OLLAMA_HOST (the Ollama
  runtime convention) after OLLAMA_API_BASE/API_BASE, normalizing a scheme-less
  value (e.g. "127.0.0.1:11434" -> "http://127.0.0.1:11434"), so users who set
  only OLLAMA_HOST see models from the server the crew will actually use.
- Empty vendor list: a successful vendor fetch returning no models is now
  authoritative instead of collapsing to the curated fallback. A reachable
  Ollama with nothing installed yields an empty list (the picker prompts for
  manual entry) rather than offering hardcoded models that aren't installed; a
  failed fetch still falls back. _from_vendor now returns [] on success-empty
  and None only when the tier is unavailable.
- Tests: ollama empty->manual, ollama down->fallback, OLLAMA_HOST resolution
  (29 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): Gemini first-page failure falls back instead of showing empty

Interaction from the prior two fixes: _fetch_gemini swallowed a first-page
error and returned [], which _from_vendor reported as a successful-empty result
and get_provider_models treated as authoritative — skipping the curated Gemini
fallback and jumping to manual entry. Now a first-page failure (nothing gathered
yet) re-raises so _from_vendor returns None and the curated list is used; a
later-page failure still keeps the partial results.
Test: test_vendor_gemini_first_page_error_uses_fallback (30 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): Gemini GOOGLE_API_KEY + Ollama recovery not blocked by cache

- Gemini ignores GOOGLE_API_KEY: _PROVIDER_KEY_ENV now maps each provider to a
  tuple of accepted env vars; Gemini accepts GEMINI_API_KEY or GOOGLE_API_KEY
  (matching crewai's own Gemini provider). A new _provider_api_key() resolver
  is used by both _from_vendor and the cache key, so a GOOGLE_API_KEY user gets
  the live models API instead of the stale curated fallback.
- Ollama recovery blocked by cache: skip the negative (fallback) cache for
  Ollama. It's a local, fast-failing server, so re-probing each call is cheap
  and lets the picker pick up real installed models as soon as the server comes
  up, instead of serving suggestions for the negative-cache TTL.
- Tests: GOOGLE_API_KEY live fetch, Ollama down->recover (32 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* style(cli): ruff format model_catalog.py

Add the blank line ruff format expects after _provider_api_key; no behavior
change. Fixes the lint-run `ruff format --check lib/` step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): don't treat 'search' substring as a non-chat model marker

The 'search' entry in _NON_CHAT_MARKERS matched anywhere in a model id, dropping
legitimate completion models like gpt-4o-search-preview and anything containing
'research' (e.g. o3-deep-research, since 'search' is a substring). Remove it;
the remaining markers (embedding/audio/image/moderation/etc.) still filter
genuine non-chat models. Test: test_search_substring_not_treated_as_non_chat (33).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* Revert "ci: ignore nltk PYSEC-2026-597 in pip-audit"

Do not suppress an unpatched security advisory to make CI green. Remove
PYSEC-2026-597 from the pip-audit ignore list; leave the scan failing so it
keeps surfacing the nltk path traversal (CVE-2026-12243). This PR should not be
merged until nltk ships a fix (or the vulnerable transitive dep is otherwise
resolved).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): exclude fine-tuned models and checkpoints from the picker

With a live OPENAI_API_KEY, /v1/models returns the user's fine-tunes and
training checkpoints (ft:..., ...:ckpt-step-N). Their recent `created`
timestamps ranked them above the base models and filled every slot, so the
picker showed a wall of `ft:gpt-4o-mini-...:crewai::...` with mangled labels and
no foundation models at all. Skip fine-tunes/checkpoints in the OpenAI-shaped
fetcher so clean base models surface; a user who wants a fine-tune can still
enter it via the picker's "Other" option. Test:
test_openai_excludes_fine_tunes_and_checkpoints (34 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

* fix(cli): cleaner model labels + filter Ollama non-chat models

Anthropic/Gemini already use vendor display names; OpenAI/Groq/Cerebras/Ollama
fall to _humanize for anything outside the curated map, which produced mediocre
labels ("GPT Oss 120b", "qwen3 32b", "Deepseek r1", "llama3.3:70b").

Improve _humanize:
- split on ':' too (Ollama tags: llama3.3:70b -> "Llama3.3 70B")
- uppercase size suffixes (70b -> 70B), acronyms OSS/IT, brand casing
  (DeepSeek, ChatGPT, QwQ)
- capitalize the leading letter of fused family+version tokens (qwen3 -> Qwen3)
  while preserving OpenAI o-series lowercase (o3, o1-mini)

Also fix _fetch_ollama: /api/tags lists everything installed, so filter
non-chat (embedding) and fine-tune entries the same way the other tiers do.

Tests: expanded test_humanize + test_ollama_excludes_embedding_models (35 total).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-07-06 20:49:52 -03:00
Lorenze Jay
e55e710df0 Implement message setup and feedback handling in AgentExecutor (#6465)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
* Implement message setup and feedback handling in AgentExecutor

- Added  method to streamline message preparation for agent execution, allowing for integration with human input providers.
- Introduced  and  methods to manage the state during feedback processing.
- Enhanced  and  methods to re-run the executor flow using existing feedback messages.
- Updated tests to verify the new message setup and feedback handling functionality, ensuring compatibility with human input providers.

* dont commit runner

* Remove xfail marker from test_crew_train_success as training feedback migration to AgentExecutor is complete.

* fix runtype errors

* fix test

* revert

* mypy fix

* handled reset iterations
2026-07-06 15:28:37 -07:00
Mani
56edf1f95f Added client name header (#6413)
- added client_name header to the 4 tavily tools to classify incoming requests as 'crewai' requests.

- This is for internal analysis

Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-07-06 14:20:59 -07:00
Vinicius Brasil
2b90117e88 Add repository agents to flow definitions (#6437)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
Inline agent and crew actions can now use repository-backed agents
without duplicating role, goal, and backstory in each definition.

Examples:
* `agent.with.from_repository: support_specialist`
* `crew.with.agents.researcher.from_repository: researcher`

`PlusAPI.get_agent` now uses the shared synchronous request path so
project loaders can fetch repository agents without nested event loops.
2026-07-02 14:28:01 -07:00
Vinicius Brasil
24901cd4f6 Support templated Flow action inputs (#6426)
Flow action inputs now support `${...}` inside strings, not only
strings that are fully wrapped in one expression. This lets authored
flows use simple prompt-like values such as:

* `query: "News about ${state.topic}"`
* `input: "Ticket ${text(state, "ticket.id", "unknown")}"`
* `sources: ["${state.primary_source}", "archive-${state.topic}"]`

Whole-expression values still preserve their runtime type, so
`${state.limit}` remains a number and `${state.domains}` remains a list.
Mixed literal and expression strings render as text.

This removes the need to build labeled strings with CEL concatenation,
which was hard to read, easy to quote incorrectly in YAML, and a poor
fit for the Flow authoring skill examples.
2026-07-02 08:57:50 -07:00
Lorenze Jay
559a9c65c4 docs: snapshot and changelog for v1.15.2a2 (#6422)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
1.15.2a2
2026-07-01 15:14:56 -07:00
Lorenze Jay
6244738d2a feat: bump versions to 1.15.2a2 (#6421) 2026-07-01 14:55:27 -07:00
Tiago Freire
8b197a7ca8 fix: include aiobotocore in the bedrock extra (#6419)
### Overview

`BedrockCompletion.acall()` (the async completion path used when a crew is kicked off asynchronously) requires `aiobotocore` to build its async client. The `bedrock` extra, however, only declared `boto3`. Crews configured with an AWS Bedrock model work fine under a synchronous `kickoff()`, since that path only needs `boto3`, but raise `NotImplementedError: Async support for AWS Bedrock requires aiobotocore` as soon as they're kicked off asynchronously, since `aiobotocore` was never installed.

The fix adds `aiobotocore` to the `bedrock` extra, so `crewai[bedrock]` installs both the sync (`boto3`) and async (`aiobotocore`) dependencies the native Bedrock provider needs. The lockfile is regenerated to match. The exception message is also corrected — it previously pointed to a `bedrock-async` extra that never existed in `pyproject.toml`.

### Changes

- `lib/crewai/pyproject.toml`: add `aiobotocore~=3.5.0` to the `bedrock` extra
- `uv.lock`: regenerated to reflect the updated `bedrock` extra
- `lib/crewai/src/crewai/llms/providers/bedrock/completion.py`: fix the install hint in the `NotImplementedError` message to reference the real `bedrock` extra instead of the nonexistent `bedrock-async`
2026-07-01 17:30:59 -04:00
Vinicius Brasil
f630c471cf Document flow agent options (#6420)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
* Document flow agent options

Document and type inline Flow agent options so authored flows can set:
* `llm.model`, `llm.max_tokens`, and `llm.max_completion_tokens`
* `planning_config.max_attempts`
* `allow_delegation`
* `max_iter`
* `max_rpm`
* `max_execution_time` in seconds

Also tell the flow skill to omit optional fields unless needed.

* Potential fix for pull request finding 'Unused import'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-01 14:08:44 -07:00
Vinicius Brasil
31a4a4e162 Squeeze AGENTS.md file (#6416) 2026-07-01 11:14:36 -07:00
Vinicius Brasil
1452ee2021 Add text helper to flow skill example (#6406)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-06-30 21:18:58 -07:00
Vinicius Brasil
629f5d537b Reject self-listening flow methods (#6405)
A method that listens to its own name can re-trigger itself or collide
with router events. Rejecting that definition keeps declarative and
Python-authored flows aligned before kickoff.
2026-06-30 19:42:01 -07:00
Vinicius Brasil
ba2dafdeda Add text helper for flow CEL prompts (#6404)
CEL string concatenation currently fails when prompt builders read
missing or null fields. This commit adds `text(root, "path", "default")`
custom CEL helper so prompt text can safely read nested state/output
values.
2026-06-30 16:45:39 -07:00
Lorenze Jay
b37505bcf9 Add streaming docs to the navigation (#6403) 2026-06-30 16:00:38 -07:00
Lorenze Jay
694881c7bf docs: snapshot and changelog for v1.15.2a1 (#6398)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
1.15.2a1
2026-06-30 13:17:53 -07:00
Lorenze Jay
958d8270db feat: bump versions to 1.15.2a1 (#6397) 2026-06-30 11:43:14 -07:00
Daniel Barreto
ba855bae2b feat: repoint template commands to crewAIInc-fde org (#6394)
Point `crewai template list`/`template add` at the crewAIInc-fde GitHub
org so the FDE template_* repos are listed and installed instead of the
crewAIInc ones.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-06-30 11:32:54 -07:00
Vinicius Brasil
c157199065 Support inline skill definitions (#6396)
* Support inline skill definitions

This commit adds inline skill loading without a need for a file. It also
DRYs the skill loading feature.

* Address code review suggestions
2026-06-30 11:22:05 -07:00
Lorenze Jay
8eed457e70 Define stream frame protocol for flows (#6391)
* Define stream frame protocol for flows

* Add direct LLM streaming helpers

* Unify flow streaming frame items

* Update flow streaming integration properties

* Drop stream frame debug runner example

* Address streaming contract review feedback

* Replay cached stream frame projections

* Remove stream frame version field

* Fix streaming contract docs link

* Preserve LLM instance state for stream events

* Address streaming review cleanup
2026-06-30 10:53:48 -07:00
Vinicius Brasil
04fec31f1e Type tool and app in CrewDefinition (#6395)
* Type tool and app in CrewDefinition

This commit fixes a bug in the CrewDefinition class where the tool and
app were not being added.

* Type mcps= parameter
2026-06-30 10:24:21 -07:00
Vinicius Brasil
1556dbea3e Add generated Flow Definition authoring skill (#6393)
* Add generated Flow Definition authoring skill

Generate a portable skill from the Flow Definition schema so agents can
author valid declarative flows with the same reference CrewAI uses to
validate them. New declarative flow projects now write this skill.

```python
from crewai.flow.flow_definition import FlowDefinition
skill = FlowDefinition.skill(skips=(), examples_format="yaml")
```

* `examples_format` accepts `"yaml"` or `"json"`.
* Supported skips: `conversational`, `non_linear_flows`, `each`, `hitl`, `persistence`, `config`, `expression_action`, `script_action`, `tool_action`

The generated skill includes authoring rules, a routed crew example, and
an API reference extracted from the Flow, action, state, agent, crew,
and task Pydantic schemas.

* Fix declarative flow scaffold without framework import

* Fix skipped expression action guidance

* Fix markdown links in skill
2026-06-30 09:13:33 -07:00
Lucas Gomide
e8dced8a2d docs: document Cost Limit rule type in Agent Control Plane (#6387)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-06-29 14:56:13 -03:00
Lucas Gomide
2b87098279 fix: cut docs version nav from Edge so new pages aren't dropped (#6349)
* fix: freeze docs version nav from Edge instead of previous release

The docs cut copied every Edge file into the new `docs/v<X.Y.Z>/`
snapshot but built that version's `docs.json` navigation by cloning the
previous frozen release and only rewriting path prefixes. Pages added to
Edge since the last release were therefore copied to disk yet never
linked in the version selector, which is why the v1.15.0 cut shipped
without the Datadog guide. `_build_new_entry` now clones the Edge nav
entry and rewrites `edge/<locale>/` to `v<new>/<locale>/`, so promoting
Edge to Latest carries every current page and nav restructuring.

* docs: link the v1.15.0 Datadog guide dropped during the cut

The v1.15.0 freeze copied `enterprise/guides/datadog` into the snapshot
for every locale but never linked it in `docs.json`, because the cut
cloned the v1.14.7 nav instead of Edge. This backfills the missing nav
reference in the `en`, `pt-BR`, `ko`, and `ar` v1.15.0 blocks so the
already-shipped page is reachable from the version selector. Pairs with
the `_build_new_entry` fix that prevents future cuts from dropping pages.

* docs: link the v1.15.1 Datadog guide dropped during the cut

The v1.15.1 cut ran before the freeze-from-Edge fix landed, so it
inherited the same bug as v1.15.0: `enterprise/guides/datadog` was
copied into the snapshot for every locale but never linked in
`docs.json`. This backfills the missing nav reference in the `en`,
`pt-BR`, `ko`, and `ar` v1.15.1 blocks so the page is reachable from the
version selector.
2026-06-29 10:03:26 -04:00
Lucas Gomide
4379c45804 docs: drop CREWAI_LOG_FORMAT references from Datadog guide (#6307)
JSON-formatted stdout is now the only supported log shape in CrewAI
Enterprise — the `CREWAI_LOG_FORMAT=json` opt-in env var is gone and
no longer needs to be configured in AMP. Removes the "Enabling JSON
output" section, the env-var setup step, the troubleshooting check,
and the `legacy text mode` comparison across the four locale copies
(`en`, `ko`, `pt-BR`, `ar`) of `docs/edge/<lang>/enterprise/guides/datadog.mdx`.
2026-06-29 09:04:49 -04:00
João Moura
6491f5a663 [docs-freeze] docs: snapshot and changelog for v1.15.1 (#6367)
Some checks failed
Mark stale issues and pull requests / stale (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
1.15.1
2026-06-27 03:50:32 -03:00
João Moura
340f6ad5b8 feat: bump versions to 1.15.1 (#6366) 2026-06-27 03:48:21 -03:00
João Moura
04adff1e0e Fix deployment page link id resolution (#6365) 2026-06-27 03:19:46 -03:00
Vinicius Brasil
e1ddb32e56 Initialize Git repositories for generated projects (#6364)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
2026-06-26 16:29:49 -07:00