crewaiinc/skills

connect-tools-and-mcp

Giving crewAI agents tools and MCP servers on crewai 1.15.x: custom BaseTool with argsschema and @tool, which crewaitools names really exist, tool caching, maxusagecount, ToolFailure, Agent(mcps=[...]) string and MCPServerStdio/HTTP/SSE forms, rewritten MCP…

ソースを見る
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

Connect Tools and MCP Servers to CrewAI Agents

Give an agent working tools - custom Python, prebuilt crewai_tools, or MCP servers - without the 0.x-era mistakes that fail silently.

Verified against crewai 1.15.22 and 1.15.23 on 2026-10-01. Live-tested on CrewAI AMP and real LLMs on 2026-10-01. Run crewai version first; if the major/minor differs from 1.15, re-verify version-sensitive rows with the ask-docs skill before trusting them.


1. Pick the mechanism

You needUseSection
A quick Python function as a tool@tool from crewai.tools3
A tool with config, state, or a documented input schemaBaseTool subclass with args_schema3
A prebuilt search/scrape/file toolcrewai_tools - but import it once to prove the name exists5
A remote MCP serverAgent(mcps=[MCPServerHTTP(...)]) - not an https:// string if the crew is deployed or uses akickoff()6, 8
An MCP server that ships with your codeAgent(mcps=[MCPServerStdio(...)]) - also works on CrewAI AMP when the server is in the package6, 10
An integration connected in your CrewAI AMP accountmcps=["<slug>"] or "<slug>#<tool>"6
Bare MCP tool names or a manual start/stop lifecycleMCPServerAdapter (needs crewai-tools[mcp])9

mcp is already a core dependency of crewai 1.15.x - native mcps= needs no extra install.


2. Imports

You probably wroteCurrent formWhat happens with the old form
from crewai_tools import BaseToolfrom crewai.tools import BaseToolImportError: cannot import name 'BaseTool' from 'crewai_tools'
from crewai_tools import toolfrom crewai.tools import toolImportError: cannot import name 'tool' from 'crewai_tools'
from crewai_tools import CodeInterpreterToola sandbox tool: E2BPythonTool, DaytonaPythonToolImportError - removed
from crewai_tools import ZapierActionsAdapterfrom crewai_tools.adapters.zapier_adapter import ZapierActionsAdapter (or top-level ZapierActionTools)ImportError at top level
from crewai.mcp import ... for the adapterfrom crewai_tools import MCPServerAdapteradapter lives in crewai_tools; native configs live in crewai.mcp
python
from crewai.tools import BaseTool, tool, ToolFailure, ToolExecutionFailedError
from crewai.mcp import (
    MCPServerStdio, MCPServerHTTP, MCPServerSSE,
    create_static_tool_filter, create_dynamic_tool_filter,
)
from crewai.mcp.exceptions import MCPConnectionError

3. Custom tools

python
from pydantic import BaseModel, Field
from crewai.tools import BaseTool, tool

class PriceInput(BaseModel):
    sku: str = Field(..., description="Product SKU, e.g. 'A-100'")
    currency: str = Field("EUR", description="ISO currency code")

class PriceTool(BaseTool):
    name: str = "price_lookup"
    description: str = "Return the unit price for a SKU. Use before quoting a price."
    args_schema: type[BaseModel] = PriceInput

    def _run(self, sku: str, currency: str = "EUR") -> str:
        return f"{sku} costs 9.99 {currency}"

@tool("Unit Converter")
def convert(km: float) -> str:
    """Convert kilometres to miles."""
    return f"{km * 0.621371:.1f} mi"

print(PriceTool().run(sku="A-100"))   # args are validated against PriceInput first
print(convert.run(km=10))

Rules that prevent real failures:

RuleFailure it prevents
Always define _run, even for an async tool_run is abstract: TypeError: Can't instantiate abstract class ... without an implementation for abstract method '_run'
Put async code in async def _run(...)Agents execute tools through _run in both kickoff() and akickoff(); an _arun override is only used when you call tool.arun() yourself
Give @tool functions a docstringValueError: Function must have a docstring at decoration time
Write the description for the LLM: what it does and when to use itThe agent picks tools by description; MCP tools in particular have opaque names (section 7)
Expect the displayed name to be sanitized@tool("Unit Converter") is offered to the LLM as unit_converter (seen in a live run with claude-haiku-4-5)
Return a ToolFailure instead of an error stringAn error string looks like data; a ToolFailure is recorded in TaskOutput.tool_failures and can abort the run (below)

Per-tool options (all on BaseTool and accepted by @tool(...) where noted):

FieldEffect (verified)
max_usage_count=N (also @tool("x", max_usage_count=N))After N runs within one task the agent gets Tool '...' has reached its usage limit of N times and cannot be used anymore. The next task or kickoff gets a fresh allowance, so enforce "once per run" side effects yourself. 0 or negative is a ValidationError
result_as_answer=True (also on @tool)The tool's return value becomes the task output; no further LLM call
cache_function=lambda args, result: boolDecides per call whether the result may be cached (section 4)
`toolfailurepolicy="ignore" \"warn" \"raise"`Also on Agent, Task and Crew; default warn. raise aborts with ToolExecutionFailedError

Failures: a tool that raises does not fail the crew. The exception text is fed back to the agent and recorded as a tool failure, and the crew finishes "successfully". When downstream code must know, return ToolFailure(...) and set tool_failure_policy="raise", or inspect result.tasks_output[i].tool_failures. Full examples: references/custom-tools.md.

Task(tools=[...]) replaces the agent's tools for that task; it does not add to them.


4. Tool result caching

SettingDefault in 1.15.22-1.15.23Effect
Crew(cache=...)FalseOpt-in. With True, a repeat call with identical arguments returns the first result without running the tool
Agent(cache=...)TrueOnly permits participation; False opts that agent out even when the crew caches
BaseTool(cache_function=...)always cacheReturn False to keep a result out of the cache

Through crewai 1.15.2 the crew cached tool results by default; from 1.15.3 it is opt-in. If you relied on the old behaviour, set Crew(cache=True) explicitly. Never enable it for live-data or state-changing tools unless their cache_function returns False.

A separate guard is not caching: if the agent repeats the exact same call twice in a row, crewai refuses the second call ("I tried reusing the same input...") whether or not caching is on.


5. crewai_tools: names that exist

crewai-tools 1.15.22-1.15.23 exports 118 names. Import a tool before you write code around it. Models routinely invent these:

Hallucinated name (ImportError)Real 1.15.22-1.15.23 name
CodeInterpreterToolremoved - use E2BPythonTool / DaytonaPythonTool
BedrockKBRetrieverBedrockKBRetrieverTool
GitHubSearchTool, GithubToolGithubSearchTool
ArxivToolArxivPaperTool
ComposioToolSetComposioTool
GoogleSearchTool, WebSearchTool, DuckDuckGoSearchToolSerperDevTool, BraveSearchTool, TavilySearchTool, EXASearchTool
PDFTextWritingTool, PGSearchToolnone
WikipediaTool, PythonREPLTool, ShellTool, CalculatorTool, HumanTool, LangChainTool, SeleniumToolnone (SeleniumScrapingTool exists) - write a custom tool

Many tools need a third-party package. When it is missing, constructing the tool asks You are missing the '<pkg>' package. Would you like to install it? [y/N] (verified for EXASearchTool, TavilySearchTool, FirecrawlSearchTool, SeleniumScrapingTool). With a terminal attached that blocks forever; with stdin closed it raises click.exceptions.Abort. Install the extra up front, e.g. uv add "crewai-tools[exa-py]". Prebuilt tools are offered to the LLM under their sanitized display name, not the class name: DirectoryReadTool appears as list_files_in_directory, FileReadTool as read_a_files_content. RAG tools (WebsiteSearchTool, PDFSearchTool, ...) fail at construction without an embedder key. Full list and extras: references/crewai-tools-names.md.


6. Native Agent(mcps=[...])

python
from crewai import Agent
from crewai.mcp import MCPServerHTTP, MCPServerSSE, MCPServerStdio, create_static_tool_filter

agent = Agent(
    role="Inventory analyst",
    goal="Answer stock questions",
    backstory="Careful with numbers.",
    mcps=[
        MCPServerHTTP(url="https://mcp.example.com/mcp",
                      headers={"Authorization": "Bearer <your-key>"}),
        MCPServerSSE(url="https://legacy.example.com/sse"),
        MCPServerStdio(command="uvx", args=["mcp-server-time"],
                       tool_filter=create_static_tool_filter(allowed_tool_names=["get_current_time"])),
        "https://docs.example.com/mcp#search_docs",   # https string, one tool (sync kickoff only - section 8)
        "acme#lookup_stock",                           # AMP-connected integration, one tool
        "acme#list_warehouses",                        # second tool = second ref
    ],
)

String refs are validated at construction; nothing connects until a task runs.

FormRule (all verified)
MCPServerStdio(command, args, env, tool_filter, cache_tools_list)Spawns a subprocess where the crew runs. The server does not inherit your environment: it gets only HOME, LOGNAME, PATH, SHELL, TERM, USER plus env=, so pass its API keys in env explicitly. No cwd or timeout field
MCPServerHTTP(url, headers, streamable=True, tool_filter, cache_tools_list)Streamable HTTP; http:// and https:// both work. Use a hostname, not an IP: http://127.0.0.1:8765/mcp makes tool names start with a digit and Anthropic models reject them (ValueError: Anthropic function name '127_0_0_1_8765_mcp_lookup_stock' must start with a letter or underscore); http://localhost:8765/mcp works
MCPServerSSE(url, headers, tool_filter, cache_tools_list)Legacy SSE servers (usually a /sse path)
"https://host/path" stringMust start with https://. Optional #tool keeps one tool. Resolves to zero tools, silently, inside a running event loop - await crew.akickoff() and crews deployed on CrewAI AMP (section 8)
"slug" / "slug#tool" stringAn integration connected in a CrewAI AMP account; legacy "crewai-amp:slug" also works. A slug the account has not connected gives zero tools and the run continues (seen on AMP)
"http://localhost:8000/mcp" or any string that is neither https:// nor a slugValidationError: ... Invalid MCP reference: 'http://...'. String references must be an 'https://' URL or a valid slug when the Agent is built. Use MCPServerHTTP for http://
"slug#a,b"Same Invalid MCP reference ValidationError. One ref per tool
"https://...#a,b"Accepted, but selects zero tools (# takes one name). One ref per tool
tool_filter namesMatched against the sanitized tool name: a server tool getForecast must be listed as get_forecast

Full examples for each transport, dynamic filters and the AMP form: references/mcp-connections.md.


7. MCP tool names are rewritten - never hard-code them

Native MCP tools are offered to the LLM as <server name>_<tool name>, then sanitized: lowercase, non-alphanumerics become _, camelCase is split, max 64 characters.

SourceName the LLM sees for tool lookup_stock
MCPServerStdio(command="python", args=["servers/inventory.py"])python_servers_inventory_py_lookup_stock
MCPServerStdio with absolute paths, e.g. /opt/app/.venv/bin/python + /opt/app/servers/inventory_server.pyopt_app_venv_bin_python_opt_app_servers_inventory_serve_a87662e9 - over 64 chars, so it is truncated and hashed and the tool name is gone. command=sys.executable does the same, locally and on AMP
MCPServerHTTP(url="http://localhost:8765/mcp")localhost_8765_mcp_lookup_stock (an IP host would start the name with a digit - section 6)
MCPServerHTTP(url="https://mcp.example.com/mcp") or the same https:// stringmcp_example_com_mcp_lookup_stock
"acme#lookup_stock" (AMP)built from the server URL the account returns, not from acme - only the _lookup_stock suffix is stable
MCPServerAdapterlookup_stock (bare)

Consequences:

  • Do not write "call the lookup_stock tool" in a task description or backstory. Describe the capability ("check stock levels with the inventory tool"), or derive the exact name at runtime. A native function-calling model usually copes (claude-haiku-4-5 told "call the lookupstock tool" called `pythonmcpserverpylookupstock), but a model on the text ReAct path fails with Action 'lookup_stock' don't exist`, and a hashed name leaves only the description to go on.
  • Keep stdio command/args short ("uvx", "npx", a relative script path) so names stay readable and under 64 characters. Absolute paths also put your filesystem layout into every prompt. A scoped npx package already uses about 45 characters: npx -y @modelcontextprotocol/server-filesystem ./data hashed list_allowed_directories to ..._data_list_4ab656ee; use MCPServerAdapter when bare names matter.
  • In code, identify a resolved native MCP tool by tool.original_tool_name, not by tool.name.

8. Timeouts, retries and failure behaviour

PathConnectPer tool callRetriesWhen the server is down
MCPServerStdio/HTTP/SSE config and AMP slugs30 s30 s3 attempts on timeout - the tool runs again each time. Live run: a 35 s tool ran 3 times (~99 s); the agent got Error executing tool: Error executing MCP tool slow_report: Operation timed out after 30 seconds as its observation, a tool failure was recorded and the crew finished. A direct tool.run() raises RuntimeError insteadkickoff raises MCPConnectionError
"https://..." string10 s, 15 s discovery60 s3 attempts (a 65 s tool ran 3 times, ~198 s) and then returns the error as a stringagent runs with no MCP tools, no error
MCPServerAdapterconnect_timeout= (default 30)no crewai timeout (a 35 s call completed)noneconstructor raises RuntimeError: Failed to initialize MCP Adapter

In 1.15.22-1.15.23 the native timeouts are module constants. No field on MCPServerStdio, MCPServerHTTP, MCPServerSSE or Agent changes them. So:

  • Keep MCP tool calls well under 30 s. Make them idempotent, because a timed-out call is re-sent. For long jobs, return a job id from one tool and poll with another.
  • Prefer config objects to https:// strings in production: they fail loudly at kickoff instead of silently dropping tools.
  • https:// strings discover tools with asyncio.run(). Inside a running event loop that fails and the agent gets zero tools with no error (only RuntimeWarning: coroutine 'MCPToolResolver._get_mcp_tool_schemas_async' was never awaited). Seen live with await crew.akickoff() and on a CrewAI AMP deployment - the agent runs without the tools, and its answer may describe tool calls it never made. The same server as MCPServerHTTP(url=...) worked in both places. Sync crew.kickoff(), including from a sync Flow step, resolves strings fine.
  • An MCP result with isError: true reaches the agent as text. It is recorded as a mcp_error tool failure, and tool_failure_policy="raise" turns it into ToolExecutionFailedError.

9. MCPServerAdapter and @CrewBase mcp_server_params

MCPServerAdapter needs the extra: uv add "crewai-tools[mcp]" (it installs mcpadapt; mcp itself is already present). Without the extra, constructing it asks You are missing the 'mcp' package. Would you like to install it? [y/N]. Under a terminal that blocks forever; with stdin closed (typical CI) it raises click.exceptions.Abort. Install the extra explicitly.

python
from mcp import StdioServerParameters
from crewai_tools import MCPServerAdapter

params = StdioServerParameters(command="python", args=["mcp_server.py"])
with MCPServerAdapter(params, "lookup_stock", connect_timeout=60) as tools:
    print([t.name for t in tools])   # ['lookup_stock'] - bare names, filtered by name
    # build agents with tools=tools and kick off INSIDE the with-block

The server starts in the constructor and stops when the with block exits. Tools used after that fail. For a remote server pass a dict and name the transport: {"url": "https://<host>/mcp", "transport": "streamable-http"}. Without "transport" the adapter speaks SSE, and against a streamable-HTTP /mcp endpoint it fails with Couldn't connect to the MCP server after <connect_timeout> seconds.

In a @CrewBase class, set mcp_server_params (and optionally mcp_connect_timeout, default 30) and call self.get_mcp_tools("name", ...) in an @agent method. crewai stops that adapter after every kickoff. Calling .crew().kickoff() a second time on the same instance made every MCP call return Event loop is closed, yet the crew still "succeeded". Build a fresh instance per run: InventoryCrew().crew().kickoff().


10. Hosted deployments: what works on CrewAI AMP

Measured on a CrewAI AMP deployment (ZIP deploy, crewai 1.15.23, anthropic/claude-haiku-4-5), one kickoff per form:

Form in the deployed crewResult
MCPServerHTTP(url="https://<public host>/mcp")Works - the model called <host>_mcp_<tool>
"https://<public host>/mcp#tool" stringZero tools, run SUCCESS - the model made up a tool call in its answer (section 8)
MCPServerStdio(command="python", args=["-m", "<pkg>.inv_server"]), server module inside src/<pkg>/Works - a stdio server shipped in the package runs inside the deployment
Same with command=sys.executableWorks (tool name hashed, section 7)
MCPServerStdio(..., env={"X": os.environ["X"]}) with X a deployment env varServer sees X; without env= it does not
MCPServerAdapter(StdioServerParameters(...)) with crewai-tools[mcp] in pyproject.tomlWorks, bare tool names
MCPServerStdio pointing at a file that is not in the deployment (a laptop path)Run fails with MCPConnectionError
MCPServerStdio(command="npx", ...)Run fails the same way - the deployment only has what your Python project installs
MCPServerHTTP at a wrong path (HTTP 404)Run fails the same way
"<slug>#tool" not connected in the accountZero tools, run SUCCESS

How a failed MCP connection looks from the API: for each MCPConnectionError run above, GET /status/{kickoff_id} answered HTTP 500 `Internal Server Error` (plain text) on every poll, minutes later too, instead of a JSON FAILED state. A plain exception in the same crew gave the documented shape: {"state": "FAILED", "status": "ValueError: ..."}. Treat a persistent 500 from /status as "the run failed", and check the MCP connection first.

Rules:

  • A stdio server runs as a child process wherever the crew runs. Ship it inside the package (src/<pkg>/server.py, started with python -m <pkg>.server) and its Python dependencies in pyproject.toml/uv.lock; a laptop path or a Node/npx server is not there.
  • For remote servers use MCPServerHTTP(url="https://<host>/mcp") (or MCPServerSSE), never an https:// string. Point deployments at a stable hostname you control, require auth on it, and do not leave temporary tunnels running.
  • Health check: a bare curl -s -o /dev/null -w "%{http_code}" https://<host>/mcp returns 406 from a healthy streamable-HTTP MCP endpoint (seen on a public server and locally). 404 means wrong path; 000/connection refused means it is down.
  • Put tokens in headers read from environment variables (os.environ["ACME_MCP_TOKEN"]), never in the URL string or in code. A stdio server gets deployment env vars only through env=.

Common mistakes

SymptomCauseFix
cannot import name 'BaseTool' from 'crewai_tools'0.x import pathfrom crewai.tools import BaseTool, tool
Can't instantiate abstract class ... '_run'Only _arun definedDefine _run (it may be async def)
Action 'lookup_stock' don't exist, these are the only available Actions: ..., or the agent never uses the MCP toolPrompt names the bare tool (lookup_stock) but the LLM sees python_..._lookup_stockDescribe the capability; derive names at runtime
ValidationError ... Invalid MCP reference: 'github#a,b'# takes one tool name["github#a", "github#b"]
mcps=["https://...#a,b"] gives no toolsSame, but https strings are not validatedOne ref per tool
ValidationError ... Invalid MCP reference: 'http://localhost:8000/mcp'Strings must be https:// or a slugMCPServerHTTP(url="http://localhost:8000/mcp")
Anthropic function name '127_0_0_1_...' must start with a letter or underscoreMCP server URL uses an IP addressUse a hostname (localhost)
https:// string MCP gives no tools under akickoff() or on AMP; the answer invents tool callsString refs cannot resolve inside a running event loopMCPServerHTTP(url=...)
GET /status keeps failing or the run never completesThe run may have hit MCPConnectionError (stdio command or file missing, wrong URL)Run the crew locally to see the error; fix the MCP connection
tool_filter keeps nothingFilter used the server's camelCase nameUse the sanitized name (get_forecast)
Run hangs at "Would you like to install it? [y/N]"Missing optional package (crewai-tools[mcp], exa-py, ...)Install the extra before running
Tool ran 3 times / side effect repeatedNative MCP call exceeded 30 s and was retriedKeep calls short and idempotent
Crew "succeeds" but the answer says the tool erroredTool exceptions are fed to the agent, not raisedReturn ToolFailure; set tool_failure_policy="raise"; check tool_failures
Stale results after enabling Crew(cache=True)Live-data tool cachedcache_function=lambda a, r: False or Agent(cache=False)
Repeated identical calls now hit the API every timeCrew cache is opt-in in 1.15.xCrew(cache=True)
Second kickoff of the same @CrewBase instance: Event loop is closedAdapter stopped after the first kickoffNew crew instance per kickoff
stdio MCP server says its API key is missing although it is in your .envstdio servers get a minimal environment, not yoursMCPServerStdio(..., env={"X_API_KEY": os.environ["X_API_KEY"]})
Works locally, fails after deploystdio server file or command (npx, a laptop path) not in the deploymentShip the server inside the package, or serve it over HTTP at a stable URL

Checklist

  • [ ] BaseTool/tool imported from crewai.tools; every crewai_tools name imported once to prove it exists
  • [ ] Custom tools define _run, have an args_schema (or typed @tool signature) and an LLM-oriented description
  • [ ] Failures returned as ToolFailure; tool_failure_policy chosen deliberately
  • [ ] Crew(cache=...) set explicitly; live-data tools excluded from caching
  • [ ] Optional packages and crewai-tools[mcp] installed up front, so no interactive prompt can block
  • [ ] One "slug#tool" ref per tool; http:// servers via MCPServerHTTP, not a string; hostnames, not IP addresses
  • [ ] No https:// string refs in deployed crews or with akickoff() - use MCPServerHTTP
  • [ ] No prompt or code depends on a bare MCP tool name; stdio commands kept short
  • [ ] stdio servers get their keys through env= (they do not inherit the crew's environment)
  • [ ] MCP tool calls finish well under 30 s and are idempotent
  • [ ] Deployed crews use HTTP/SSE MCP servers at a stable URL that returns 406 on a bare GET, or stdio servers shipped inside the package
  • [ ] A fresh @CrewBase instance per kickoff when using mcp_server_params

References

  • Custom Tools - BaseTool, @tool, async, ToolFailure and failure policy, caching, usage limits, with runnable examples
  • MCP Connections - every mcps= form, filters, name derivation, timeouts, MCPServerAdapter, @CrewBase, deployment
  • crewai_tools Names - the full 1.15.22-1.15.23 export list, hallucinated names, extras and construction behaviour
  • Public docs: https://docs.crewai.com/en/concepts/tools and https://docs.crewai.com/en/mcp/overview

For related skills:

  • check-crewai-api - current Agent/Task/Crew API and imports beyond tools
  • design-agent - choosing how many tools an agent gets and writing role/goal/backstory
  • test-crewai-project - driving tool calls offline with a stub LLM
  • deploy-to-amp - getting a project with MCP connections onto CrewAI AMP
  • ask-docs - query the live docs when the installed version differs
同じリポジトリから

関連する Skills

すべての Skills
crewaiinc
コミュニティ

ask-docs

Query the official CrewAI documentation for answers. Use when the user has a CrewAI question that isn't fully covered by the getting-started, design-agent, design-task skills — e.g., specific API details, configuration options, advanced features, troubleshooting errors, enterprise features, tool references, or anything where the latest docs are the best source of truth.

導入数
2
GitHub Stars
45
更新日
10月6日
crewaiinc
コミュニティ

build-flow

Building CrewAI Flows on crewai 1.15.x: structured (Pydantic) vs dict state and state.id, @start/@listen/@router wiring, or/and semantics, router labels vs method names, @persist (correct import, where it stores state, restorefromstateid), checkpointing with CheckpointConfig, @humanfeedback and HumanFeedbackResult.feedback, plot(), calling crews and agents from flow methods, kickoff inputs, and the crewai create flow scaffold. Use when writing or debugging a Flow subclass or main.py with from cr

導入数
2
GitHub Stars
45
更新日
10月6日
crewaiinc
コミュニティ

call-deployed-crew

Calling a crew or flow deployed on CrewAI AMP over HTTP: the bearer token and deployment URL, GET /inputs, POST /kickoff with the {\"inputs\": {...}} body, which input keys are required ({placeholder} tokens), polling GET /status/{kickoffid} with a deadline and backoff, terminal states and where the result lives, webhooks, POST /resume, slow first calls, and writing crews that stay correct when they are kicked off repeatedly or concurrently. Use when writing a client, script, backend or frontend

導入数
2
GitHub Stars
45
更新日
10月6日
crewaiinc
コミュニティ

check-crewai-api

Current crewai 1.15.x API versus the 0.x API that coding assistants remember: imports, Agent/Task/Crew parameters and defaults, kickoff variants, CrewOutput fields, LLM model strings and provider extras, structured output (outputpydantic, responsemodel, responseformat), guardrails, unified Memory, knowledge embedders, the crewai create crew wizard vs --classic, reset-memories flags, and removed features. Use when writing, reviewing, or debugging any crewai code, before trusting remembered crewai

導入数
2
GitHub Stars
45
更新日
10月6日