@asynccontextmanager
async def lifespan(app: FastAPI):
async with AsyncConnectionPool(
conninfo=settings.db.connection_string,
max_size=settings.db.connection_pool_size,
timeout=settings.db.connection_timeout,
kwargs={
"autocommit": True,
"row_factory": "dict_row",
"prepare_threshold": 0
}) as pool:
await pool.wait()
app.async_connection_pool = pool
yield
await app.async_connection_pool.close()
async def get_agent_memory(request: Request):
async with request.app.async_connection_pool.connection() as connection:
checkpointer = AsyncPostgresSaver(connection)
await checkpointer.setup()
yield checkpointer
...
graph = StateGraph(AgentState)
...
self.agent = graph.compile(checkpointer=checkpointer)
...
app = FastAPI(lifespan=lifespan)
app.add_middleware(ElasticAPM, client=apm_client)
...
...
await self.agent.aget_state(config)
...
await self.agent.ainvoke(Command(resume=_input), config)
...
await self.agent.ainvoke(_input, config)
...
Traceback (most recent call last):
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.scope, self.receive, self.send
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/elasticapm/instrumentation/packages/asyncio/starlette.py", line 48, in call
return await wrapped(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 187, in __call__
raise exc
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/elasticapm/contrib/starlette/__init__.py", line 199, in __call__
await self.app(scope, _request_receive or receive, wrapped_send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 714, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 734, in app
await route.handle(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 288, in handle
await self.app(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 76, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 73, in app
response = await f(request)
^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/fastapi/routing.py", line 301, in app
raw_response = await run_endpoint_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<3 lines>...
)
^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/fastapi/routing.py", line 212, in run_endpoint_function
return await dependant.call(**values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/src/api/routes/routes.py", line 27, in message_handler
response = await graph.send_message(...)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/src/services/agents/graph.py", line 24, in send_message
return await self.my_agent.invoke(...)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/src/services/agents/my_agent.py", line 75, in invoke
state = await self.agent.aget_state(config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/langgraph/pregel/__init__.py", line 1019, in aget_state
saved = await checkpointer.aget_tuple(config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user_name/src/my_app/.venv/lib/python3.13/site-packages/langgraph/checkpoint/postgres/aio.py", line 187, in aget_tuple
await cur.execute(
~~~~~~~~~~~^
self.SELECT_SQL + where,
^^^^^^^^^^^^^^^^^^^^^^^^
args,
^^^^^
binary=True,
^^^^^^^^^^^^
)
^
Describe the bug: Hi, I'm trying to integrate my app with ElasticAPM and getting strange behaviour around langgraph functionality when ElasticAPM middleware is added (
TypeError: AsyncCursorProxy.execute() got an unexpected keyword argument 'binary').To Reproduce
AsyncConnectionPoolinstrumented like this:StateGraphinstrumented and compiled like the following (most of the custom code is omitted):FastAPIapp withElasticAPMmiddleware like so:All of this leads to the
TypeError: AsyncCursorProxy.execute() got an unexpected keyword argument 'binary'(see traceback below).Notes:
app.add_middleware(ElasticAPM, client=apm_client)is commented out, then everything works just fine.MemorySaver, then theElasticAPMmiddleware does not break the flow so it looks like the combination ofFastAPI,langgraph,AsyncPostgresSaverandElasticAPMmiddleware makes the deal.Environment (please complete the following information)
Additional context
Traceback
Agent config options
Click to expand
requirements.txt(in my case Poetry'spyproject.toml):Click to expand