Commit Graph
2903 Commits
Author SHA1 Message Date
ViditOstwal c091458474 Merge branch 'main' into my-crewAI 2026-09-17 13:59:53 +05:30
Sharoon SharifandVidit Ostwal 5c33fe4c71 fix: close sqlite connections in flow persistence and sqlite provider (#7511)
Apply the same contextlib.closing pattern accepted in #7493 to the nine
remaining library-side sqlite3.connect sites: SQLiteFlowPersistence
(init_db, save_state, load_state, save_pending_feedback,
load_pending_feedback, clear_pending_feedback) and SqliteProvider
(checkpoint, prune, from_checkpoint). The connection context manager
only commits or rolls back, so the connections survived in a reference
cycle and kept flow_states.db / checkpoint databases locked on Windows.
Also close the read-back connections in test_checkpoint.py, which made
its TemporaryDirectory cleanup fail on Windows for the same reason.
Add lifecycle and failure-path regression tests.

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-17 07:37:38 +00:00
子涵的代码日记 b34023d6bc fix(llm): collapse multimodal content with the shared helper (#7527)
For response_model calls the messages are flattened into one prompt for
InternalInstructor with an f-string, so a multimodal content list reached the
model as its Python repr. AGENTS.md's "Message Content" section says never to
str() the content; use message_content_text() instead.
2026-09-17 12:44:06 +05:30
Lorenze Jay 7a01af2791 [docs-freeze] docs: snapshot and changelog for v1.15.22 (#7521) 1.15.22 2026-09-16 15:09:40 -07:00
Lorenze Jay b0343eb75f feat: bump versions to 1.15.22 (#7520) 2026-09-16 22:04:49 +00:00
Vinicius Brasilandgithub-actions[bot] 64ab0112bd Support aliases as connection identifiers (#7519)
* Support private app connections

App selectors only accepted UUID connection identifiers, so apps=["github@private"] failed validation.

Accept connection aliases and route them through Clipper like UUID identifiers. This supports private connections and future platform aliases without client releases.

* chore: update tool specifications

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-17 00:54:00 +05:30
5990ead5ec feat(cli): record why a deployment create failed (#7451)
* feat(cli): record why a deployment create failed

`crewai deploy create` counts every attempt (`Create Crew Deployment`) and every
success (`Crew Deployment Created`), but the gap between them carried no cause:
among clients able to emit the success span, the CLI succeeds 96.7% of the time
and the run TUI 36.4%, and nothing said why. A third span, `Crew Deployment
Failed`, now fires for every failure after the attempt is counted, with a closed
vocabulary `reason` (api_4xx, api_5xx, invalid_response, network_error,
zip_error, user_declined, unexpected), the HTTP `status_code` when the API
answered, and the existing `source`. Never the error message.

The request path is factored into `_request_crew_creation`; every exception is
classified, reported and re-raised unchanged, so CLI and TUI behaviour is the
same as before. HTTP failures are classified before `_validate_response`, which
still prints and exits as it did.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(cli): classify deploy create failures by status and by stage

Review fixes on the failure span. Check the HTTP class before the body so a
gateway's HTML page counts as api_4xx / api_5xx with its code. Treat a 2xx
whose body is not a JSON object carrying uuid and status as invalid_response
and exit cleanly, instead of emitting a success span and crashing in the
display step. Recognise archive failures by a dedicated ArchiveError
(a ValueError) raised from create_project_zip, so the git helpers' own
ValueErrors no longer read as zip_error; a failed ZIP write is wrapped and
its partial file removed.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(cli): treat staging and temp-file failures as archive errors

`create_project_zip` only wrapped the ZIP write, so an `OSError` while
staging files or creating the temporary archive escaped as a bare
`OSError` and the deploy command recorded it as `unexpected` instead of
`zip_error`. The archive boundary now covers staging, temp-file creation
and the write; the staging directory is removed on every path, and no
partial archive is left behind.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* feat(cli): tell a non-JSON 2xx apart from a non-creation 2xx

A proxy's 200 HTML page and a JSON body missing the creation fields were
both recorded as `invalid_response`. They are different failures, one in
the network path and one in the API contract, so the deploy failure span
now records `invalid_json` for the first and `invalid_creation_response`
for the second. Requested in review.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 23:37:14 +05:30
32a9d2ae7b feat(tracing): collect human feedback and pause events in the trace (#7499)
* feat(tracing): collect human feedback and pause events in the trace

The trace listener subscribed to method and conversation events but not to
the review-gate events or the pause events, so a `@human_feedback` gate
reached the trace only as method_execution_started/finished. A trace could
not say that a run stopped for review, what the reviewer was shown, or what
they answered.

Subscribe to HumanFeedbackRequestedEvent, HumanFeedbackReceivedEvent,
MethodExecutionPausedEvent and FlowPausedEvent through `_handle_action_event`,
as the conversation events are, with the event's own type as the trace type.
Each is a whole-event payload via the default serialization path; no change
to `_build_event_data` or `complex_events`.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(tracing): register the gate and pause handlers through _on, keeping the execution-uuid gate

The four new handlers, and the conversation handler this branch had switched by
mistake, registered with event_bus.on and so ran while a kickoff owned an execution
uuid — the case where the OTEL session records these events and the legacy collector
must stay idle. Restored to self._on like every other handler; a test binds an
execution uuid and asserts none of the five are collected into a legacy batch.
Docstrings on the handlers (review bot coverage note).

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* test(tracing): under a tracing kickoff the session records the gate and pause events and the legacy batch stays empty

Two real flows under an in-memory tracing session (the lifecycle tests' pattern): a
@human_feedback gate answered at the console records human_feedback_requested and
human_feedback_received as spans; an async provider that parks the flow records
method_execution_paused and flow_paused. In both the legacy collector, gated by _on,
collects none of the four. Review bot: the uuid-gated test alone would have passed
with the session registrations missing.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 16:41:09 +00:00
c0af9badb8 fix(skills): accept CRLF in inline skill definitions (#7504)
Co-authored-by: wangtaotaotao95 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 19:35:35 +05:30
Ray b4fd395d8d fix(rag): load text file URLs through the safe fetcher (#7506) 2026-09-16 13:51:05 +00:00
Sharoon SharifandVidit Ostwal 2c24b95eae fix(memory): close sqlite connections in kickoff task outputs storage (#7493)
* fix(memory): close sqlite connections in kickoff task outputs storage

`with sqlite3.connect(...) as conn` only commits or rolls back; it never
closes the connection, which then survives in a reference cycle until a
cyclic GC pass. Every Crew kept an open handle on
latest_kickoff_task_outputs.db, so on Windows the file stayed locked and
any later delete, rename or temp-dir cleanup failed with PermissionError
(WinError 32). Wrap each connection in contextlib.closing, keeping the
existing commit/rollback semantics, and add regression tests.

* test(memory): cover rollback and close on a failed write

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 07:47:39 +00:00
d2190c2a7d fix(agents): carry from_cache on the native tool path's ToolUsageFinishedEvent (#7501)
`_execute_single_native_tool_call` reads the tools handler's cache and
skips the tool body on a hit, but emitted its ToolUsageFinishedEvent
without `from_cache`, so the bus — and every trace built from it — saw a
replayed native function call as a live one. The text-protocol path
(ToolUsage.on_tool_use_finished) already carried the flag. One kwarg.

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 12:47:31 +05:30
c1beddf1a6 feat(llm): add llm_overlay contextvar to route agent roles to models (#7500)
A per-run caller sometimes needs specific agents on a different model
without editing the code that builds them. `crewai.llm_overlay` adds a
process-context `role -> model` overlay:

    with llm_overlay({"Researcher": "openai/gpt-4o"}):
        crew.kickoff()

The overlay is read in the only two places an agent resolves its model from
its role: `Agent.post_init_setup` and `LiteAgent.setup_llm`. When the role is
a key, `create_llm` receives the mapped model instead of the declared `llm`;
otherwise, and outside the block, nothing changes. `create_llm` itself stays
role-blind.

The overlay is a ContextVar, so it follows the calling context and is always
reset on exit. It does not cross plain threads; callers threading agents must
propagate the context with `contextvars.copy_context().run(...)`. The module
docstring says so and a test pins the behaviour.

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 12:41:47 +05:30
Swapnil YadavandVidit Ostwal a59cf26f56 fix(files): raise ValueError instead of bare raise in get_uploader (#7283)
* fix(files): return None instead of bare raise in get_uploader

get_uploader is documented to return None for an unsupported provider, and
every caller branches on `if uploader is None`. Two fallthrough paths ran a
bare `raise` with no active exception, so an unknown provider and a Bedrock
provider without a configured S3 bucket raised
"RuntimeError: No active exception to reraise" instead of returning None.

Return None in both paths and widen the return types to `... | None`. The
Bedrock "not configured" guard now treats a falsy bucket_name (None or "") as
unconfigured, not only an absent one. The except ImportError re-raises are
unaffected.

Fixes #7282

* fix(files): raise ValueError from get_uploader for unknown/unconfigured providers

Per review, raise a ValueError with a concrete reason instead of returning
None. Returning None let the resolver silently fall back to inline and hid the
misconfiguration from the user, so the docstring no longer promises None and
the return types drop `| None`. The Bedrock guard also treats a falsy
bucket_name (None or "") as unconfigured. The ImportError re-raises are
unchanged.

cleanup skips providers it cannot build an uploader for, so it routes
get_uploader through a local helper that treats the ValueError as
"unavailable" and continues the pass.

* refactor(files): surface get_uploader errors through the resolver

Follow-up to review. get_uploader now raises ValueError, so _get_uploader no
longer promises FileUploader | None: it returns the uploader and lets the error
propagate through resolve() to the caller instead of swallowing it and falling
back to inline. Drop the now-dead `if uploader is None` checks at the two
upload call sites.

Also make the unknown-provider ValueError list the supported providers, and add
a happy-path test that a configured provider returns its uploader.

* fix(files): surface uploader lookup errors in async batch resolution

aresolve_files gathers with return_exceptions=True, which was silently dropping
files when _get_uploader raised (a missing provider SDK, or an unknown or
unconfigured provider). A batch shares one provider, so such a lookup failure
applies to every file: re-raise ValueError and ImportError to surface it,
matching the sync resolve_files path. Genuine per-file upload errors are still
logged and skipped.

* fix(files): only re-raise uploader config errors in async batch resolution

The earlier fix re-raised any ValueError or ImportError from
asyncio.gather(return_exceptions=True), so one unrelated per-file error
(for example a stream that raises ValueError when read) aborted the whole
batch instead of the intended log-and-skip.

_get_uploader now translates the lookup failure into a dedicated
UploaderConfigurationError, and aresolve_files re-raises only that, since
it applies to every file for the provider. Ordinary per-file failures stay
best-effort. Adds regression tests for the wrap, a provider-setup error
surfacing from the batch, and an unrelated per-file error skipped while
the rest resolve.

* style(files): apply ruff import sort and formatting to resolver tests

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 06:41:25 +00:00
1c64c84cd8 feat(tracing): carry task_prompt and output in agent_execution payloads (#7498)
`agent_execution_started` and `agent_execution_completed` are in
`complex_events`, so `_build_event_data` hand-builds their payloads. Those
payloads shipped only agent_role/goal/backstory and dropped two required bus
fields: `AgentExecutionStartedEvent.task_prompt` and
`AgentExecutionCompletedEvent.output`. A trace therefore said which agent ran
but not what it was asked or what it answered.

Add `task_prompt` to the started payload and `output` to the completed one,
whole and untruncated. No new event types, no TraceEvent change.

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 11:56:33 +05:30
9473098af5 fix(flow): support non-primitive types in SQLiteFlowPersistence (#7358) (#7376)
* fix(flow): support non-primitive types in SQLiteFlowPersistence (#7358)

* test(flow): add docstrings to test classes and step methods

* fix(flow): serialize Decimal and Path as strings in SQLite persistence

* fix(flow): dump BaseModel with mode=python to allow fallback serialization on Any fields

* fix(flow): prioritize model_dump mode=json with fallback to mode=python

* ci: re-trigger test suite

---------

Co-authored-by: Rohit Kanithi <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-16 06:01:07 +00:00
João MouraandClaude Fable 5.1 6b6a39d503 fix(events): Improve coding agents instructions (#7447)
* feat: scaffold project with assistant instruction files

- Updated project creation to include `CLAUDE.md` and `GEMINI.md` that import `AGENTS.md`, ensuring consistent guidance across coding assistants.
- Implemented utility functions to copy assistant instruction files during project setup.
- Enhanced documentation in `AGENTS.md` to emphasize the importance of keeping telemetry enabled for optimal performance.
- Added tests to verify the correct scaffolding of assistant instruction files and their contents.

* fix(cli): neutral observability guidance in scaffolded AGENTS.md

- State the observability rule as the user's decision, never a fix for
  console warnings, speed, or a "clean" configuration
- Rewrite the AMP section as built-in capabilities: no "free",
  "proactively", "sales pitch", or scripted pitches
- Turn the research mandate into a list of sources to consult when
  version details matter
- Retarget the scaffold tests to the new wording

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(cli): scaffold assistant files for JSON crews and harden telemetry tests

- create_json_crew, the default `crewai create crew` path, now copies
  AGENTS.md, CLAUDE.md and GEMINI.md; AGENTS.md documents the JSON layout
- span helper no longer depends on OTEL_SDK_DISABLED being popped by an
  earlier test; thread-scope test stops its worker before leaving the mock
- single import style in the shutdown test

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
2026-09-16 02:07:57 -03:00
Lorenze Jay 993a96c4e0 feat(tracing): port trace events sessions to OSS (#7464)
* feat(tracing): port enterprise event sessions to OSS

* fix(tracing): address review findings and verify concurrent exports

* fix(tracing): keep redactor ownership in enterprise integrations

* test(tracing): isolate intentional failures from cleanup assertions
2026-09-15 13:09:40 -07:00
Vidit Ostwal 8949e8a3cf Merge branch 'main' into my-crewAI 2026-09-15 23:04:54 +05:30
Sharoon Sharif 756d8d33c8 fix(cli): read json checkpoints as utf-8 (#7491)
JsonProvider writes checkpoints with encoding="utf-8" and the runtime
serialises non-ASCII text verbatim, but the checkpoint CLI still opened
them with the platform default encoding. On Windows (cp1252) `crewai
checkpoint info` raised UnicodeDecodeError and `list` showed a 0-byte
entry for any checkpoint containing non-ASCII text. Open the files as
UTF-8 and add regression tests for the three readers.
2026-09-15 16:52:54 +00:00
Vidit Ostwal 667420f207 ci: grant PR comment fallback permission (#7489) 2026-09-15 21:19:35 +05:30
Sharoon SharifandVidit Ostwal 0e2fa7ec24 fix(cli): overwrite stale poetry.lock backup on windows (#7463)
* fix(cli): overwrite stale poetry.lock backup on windows

os.rename raises FileExistsError on Windows when poetry-old.lock already
exists from a previous run, so a second `crewai update` crashed there
while POSIX silently replaced the file. Use os.replace, which overwrites
on every platform, and add a regression test.

* test(cli): add docstrings to update_crew tests

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-15 15:37:03 +00:00
哈基米andVidit Ostwal b66f3f215a fix(azure): key streamed tool calls by wire index (#7487)
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-15 20:57:04 +05:30
絜矩 7b79662372 fix(gemini): preserve fileData content parts (#7479)
* fix(gemini): preserve fileData content parts

* test(gemini): cover media-only fileData messages
2026-09-15 14:52:07 +00:00
c6ff78650e fix(memory): honor read_only on update() and recall() access times (#7369)
`Memory.read_only` was enforced only on `remember()` and `remember_many()`.
Two other paths still mutated the backing store:

- `update()` re-embedded the supplied content and wrote the record back.
- `recall()` refreshed `last_accessed` through `touch_records()`, so simply
  reading a read-only memory left a persistent trace.

Both now respect the flag, so a read-only Memory leaves stored records
unchanged. `update()` returns the existing record untouched rather than
raising, matching the silent no-op behaviour of `remember()`. Explicit
deletion through `forget()`/`reset()` is deliberately unaffected.


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

Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-15 11:20:49 +00:00
Vidit Ostwal 6f14e866db Merge branch 'main' into my-crewAI 2026-09-15 11:46:43 +05:30
66ef97c73e fix(llms): send reasoning_effort to every openai reasoning model (#7187)
* fix(llms): send reasoning_effort to every openai reasoning model

The completions path gated the parameter behind
is_o1_model = "o1" in model.lower(), a literal substring test. gpt-5, o3 and
o4-mini contain no "o1", so an explicitly configured effort was dropped and the
model thought at the server default. The request still succeeded, so nothing
surfaced -- one measured extraction ran 6.2s with the setting applied against
149.7s with it dropped.

The gate could not be widened: is_o1_model also drives
supports_function_calling, supports_stop_words and the system->user message
rewrite, so marking gpt-5 as an o1 model would report that it cannot call
tools. The parameter is forwarded unconditionally instead, matching the
responses path, and a model that genuinely does not support it says so in a 400
that is retried once without the key.

Also adds "minimal" to LLM.reasoning_effort, which gpt-5 accepts and the
Literal omitted, so the cheapest setting was unreachable on the typed surface.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>

* refactor(llms): gate reasoning_effort on model shape, not every model

Forwarding to every model made a non-reasoning model pay a rejected request
and a retry on every call. `_supports_reasoning_effort` matches on shape
instead -- the o-series, and GPT generation 5 onwards -- so gpt-4o and gpt-4.1
never send the parameter at all.

Matched by shape rather than by a list of names so a new member of an existing
family works without a release here; gpt-6 and o5 already classify correctly.
The unsupported-parameter retry stays as a safety net for the case the shape
match is wrong for a future family, where it costs nothing when the match is
right.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>

* fix(llms): honour reasoning_effort on compatible servers and fine-tunes

Review follow-ups. A fine-tune (ft:<base>:...) is judged by its base model.
On an OpenAI-compatible server -- anything whose effective base URL is not
api.openai.com, whether set explicitly, via env, or by a provider subclass --
the model name is the server's namespace and says nothing about support, so an
explicit setting is sent as configured; a 400 naming the parameter, in whatever
words the server uses, is recovered by retrying without it, unless it reads as
a complaint about the value. A model that rejected the parameter is remembered
per (endpoint, model) for the process so the rejected call is paid once, and
the drop is logged as a warning since a configured setting is not being
applied. The Literal also gains "xhigh", the remaining value the SDK accepts.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(llms): recover reasoning_effort only on evidence the parameter is unknown

Two review follow-ups. The endpoint check now uses the same base URL precedence
as the client itself, so a `client_params` override selects the server. And a
rejection is recovered only when the message says the field is not one the
server knows -- OpenAI's two shapes plus the common compatible-server wordings
("unknown field", "Extra inputs are not permitted") -- rather than any 400 that
lacks a value-sounding word. A pydantic enum complaint such as "Input should be
'low', 'medium' or 'high'" names the parameter but is about its value, and
surfaces instead of being dropped.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(llms): remember a reasoning_effort rejection only after the retry succeeds

Two review points on the reasoning_effort fallback. The rejection was recorded
before the retry ran, so a retry that died for an unrelated reason (a dropped
connection, say) silently stopped sending the configured effort for the rest of
the process even though a call without it had never succeeded; the (endpoint,
model) is now remembered only once the retry returns. And _effective_base_url
accepted only a str override in client_params while the SDK, and
_get_client_params, accept httpx.URL too, so a compatible deployment configured
with a URL object was detected as OpenAI and its rejection keyed under the wrong
endpoint; both forms are normalised to the string the client calls.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 19:14:39 +00:00
Vidit Ostwal 0237ef262c Merge branch 'main' into my-crewAI 2026-09-14 22:26:53 +05:30
theaterandVidit Ostwal a225c1b373 fix(cli): don't crash the run TUI when streamed output contains a literal [...] (#7435)
* fix(cli): reject non-serializable literal_eval results in TUI JSON formatting

_try_parse_structured() accepted any dict/list coming out of
ast.literal_eval(), including values json.dumps() cannot encode such as
[Ellipsis] from a literal [...]. _format_json_in_text() then raised
TypeError: Object of type ellipsis is not JSON serializable, which
propagated through _tick and cancelled the whole crew run.

Validate the parsed object with json.dumps() inside
_try_parse_structured() so only JSON-serializable dict/list values are
returned; anything else falls back to the original text. Fixes #7434.

* fix(cli): contain RecursionError in the TUI JSON formatting boundary

A streamed structure nested deeper than the JSON backend can walk could
raise RecursionError out of _try_parse_structured (from json.loads) or
out of the render-path dumps, escaping _tick and losing the TUI update.

Catch RecursionError when loading, and validate literal_eval results
with the exact kwargs the render path uses, so any structure the render
cannot encode is rejected at the boundary and the raw text renders
instead.

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 20:41:33 +05:30
ShivangiandVidit Ostwal a328710007 fix: reject replay when stored tasks differ (#7155)
* fix: reject replay when stored tasks differ

* fix: validate replay task descriptions

* fix: reject ambiguous replay task identities

* fix: persist stable replay task keys

* test: align legacy replay fixture

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 15:52:31 +05:30
ModusensusandVidit Ostwal 7e80d94921 fix: use sys.platform guards so mypy passes on Windows (#7401)
mypy does not narrow on `platform.system()`, so Windows-based contributors
get 8 spurious attr-defined/unused-ignore errors from the termios and
resource imports. Switch to `sys.platform` comparisons, which mypy
understands natively, and drop the now-unneeded type-ignore comments.

Fixes #7400

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 14:38:50 +05:30
9393a47f31 fix(agents): request the forced final answer as a user turn (#7450)
* fix(agents): request the forced final answer as a user turn

When an agent reaches max_iter, handle_max_iterations_exceeded appended
the "give your best final answer" instruction as an assistant message and
relied on assistant prefill to make the model continue it. Current Claude
models (Opus 5, Sonnet 5, Fable 5.x, the 4.6+ family) reject a request
that ends on an assistant turn with a 400, after the whole iteration
budget has already been spent.

The instruction is now appended as a user turn, which every provider
accepts. The handler's formatted_answer parameter is dropped: every
caller had already appended that text as the last assistant message, so
prefixing it again only duplicated history.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* fix(agents): stop the lite agent loop after the forced final answer

LiteAgent._invoke_loop fell through after handle_max_iterations_exceeded
and issued a regular LLM call on the same history, discarding the forced
answer. Break out of the loop the way CrewAgentExecutor already does, and
assert a single LLM call in the test.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 11:52:08 +05:30
Melanie Hart BuehlerandVidit Ostwal 21678f8ac6 docs(rag): add xpu to embedding device options (#6808)
* docs(rag): add xpu to embedding device options

* address copilot review

* docs(rag): sync Korean and Portuguese RagTool pages

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-14 05:51:43 +00:00
Mairaarshad19 b38f129eb0 chore: stop tracking .env.test 2026-09-13 19:29:45 +05:00
Mairaarshad19 06485ca713 test: add VCR cassette for gemini-3.8-flash 2026-09-13 19:22:16 +05:00
Vidit Ostwal 1546071f2b Merge branch 'main' into my-crewAI 2026-09-12 19:26:46 +05:30
Vidit Ostwal 894898f84c ci: welcome first-time contributors after merge (#7397)
* ci: welcome first-time contributors after merge

* ci: welcome first-time contributors after merge

* ci: support fork contributor welcome comments

* ci: minimize contributor welcome permissions
2026-09-12 01:16:17 +05:30
Vidit Ostwal 93ad4d67c4 feat: validate platform integrations during crew setup (#7385)
* feat: validate platform integrations during crew setup

* fix: clarify platform integration validation

* refactor: split platform authentication workflow

* feat: list connected platform integrations
2026-09-11 12:20:33 -07:00
Vidit Ostwal d20845f0a3 feat: add platform tools to JSON crew wizard (#7384)
* feat: support platform tools in JSON crews

* style: clarify platform integration labels

* fix: avoid repeating tool picker title

* fix(platform): surface JSON tool discovery errors
2026-09-11 12:13:55 -07:00
Vidit Ostwal e1f3c4bdd4 feat: expose CrewAI Platform application catalog (#7383)
* feat: expose platform application catalog

* refactor: centralize platform application catalog

* fix: preserve platform application typing

* chore: remove unused platform app export
2026-09-11 21:02:00 +05:30
Vidit Ostwal d5c7bac505 chore: update OpenRouter tool specifications (#7387) 2026-09-11 12:16:05 -03:00
Vidit Ostwal 004f7b58d5 test(bedrock): isolate session credential test (#7388) 2026-09-11 14:23:03 +00:00
mairaarshad19 ee54aed25d Merge branch 'main' into my-crewAI 2026-09-11 16:12:59 +05:00
Vidit Ostwal c5759ce854 test(bedrock): verify environment credentials (#7375)
* test(bedrock): verify environment credentials

* test(bedrock): isolate credential environment test
2026-09-10 23:07:50 -07:00
monkscodeandVidit Ostwal 5704ea08eb fix(agents): keep null in the task output schema embedded in the prompt (#6775)
* fix(agents): keep null in the task output schema embedded in the prompt

build_task_prompt_with_schema embeds the task output schema into the prompt
via generate_model_description, whose strip_null_types defaults to True.
Combined with ensure_all_properties_required, an Optional[str] = None field
reaches the model as a required, non-nullable string, contradicting the
provider-side response schema generated from the same model.

That sanitizer targets OpenAI strict function-calling schemas. This call site
produces prompt prose, where those constraints do not apply.

Pass strip_null_types=False, matching the existing call for tool schemas in
utilities/agent_utils.py.

Fixes #6774

* test(agents): cover the output_json branch of the prompt schema

build_task_prompt_with_schema embeds a schema on both the output_json and
the output_pydantic branch, and this PR changes both. The regression test
only built a Task with output_pydantic, so the output_json branch shipped
unpinned.

Parameterize over both output attributes. Checked on this branch with the
fix reverted: both cases fail on the missing anyOf, and both pass with it.

Also compare the anyOf members as a set, so member order is not part of the
test contract.

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-10 13:46:16 +05:30
Vidit Ostwal f2a646b710 Merge branch 'main' into my-crewAI 2026-09-10 12:57:14 +05:30
幻andVidit Ostwal 8616dca5c0 docs: list all workspace packages (#6678)
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-10 12:51:37 +05:30
Vidit Ostwal 4c5488f1ae Merge branch 'main' into my-crewAI 2026-09-10 12:26:37 +05:30
Gamal OsamaandVidit Ostwal c860613c7a feat(embeddings): add openrouter as a supported embedding provider (#7127)
* feat(embeddings): add openrouter provider type definitions

* feat(embeddings): implement OpenRouterProvider

* feat(embeddings): export openrouter provider package symbols

* feat(embeddings): register openrouter in allowed embedding providers

* feat(embeddings): register openrouter provider and overloads in factory

* feat(tools): add openrouter embedding service support

* test(embeddings): add comprehensive openrouter provider and factory tests

* test(embeddings): add openrouter build test in embedding factory

* test(embeddings): add openrouter model key alias and env tests

* test(tools): add openrouter tests for embedding service

* docs: add openrouter embedder configuration example

* docs(ar): sync openrouter embedder translation

* docs(ko): sync openrouter embedder translation

* docs(pt-BR): sync openrouter embedder translation

* feat(embeddings): allow model alias and None fields in OpenRouterProviderConfig

* fix(tools): resolve EMBEDDINGS_OPENROUTER_API_KEY before OPENROUTER_API_KEY

* test(tools): add regression tests for openrouter env var precedence and fallback

* feat(embeddings): drop organization_id and resolve api_key via OPENROUTER_API_KEY only

* fix(tools): use OPENROUTER_API_KEY in embedding service and update tests

* docs: switch openrouter knowledge example to model_name and document OPENROUTER_API_KEY

* fix(tools): default openrouter model to namespaced openai/text-embedding-3-small

---------

Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-10 12:24:15 +05:30
4bfdb0df67 fix(tools): align DOCXSearchTool with standard RAG fixed schema pattern (#7356) (#7357)
Co-authored-by: Rohit Kanithi <[email protected]>
Co-authored-by: Vidit Ostwal <[email protected]>
2026-09-10 11:16:08 +05:30