pydantic ext: auto_wrap_tools + async event_stream_handler crashes with 'Object of type coroutine is not JSON serializable' on first tool call
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
Línea de trabajo
Comienza en restate/ext/pydantic/_agent.py, en wrapped_event_stream_handler, y luego lee server_context.py alrededor de create_run_coroutine para confirmar cómo se clasifica y serializa el callable. Ejecuta la reproducción proporcionada con un async event_stream_handler, una llamada a una herramienta y auto_wrap_tools=True; se considera terminado cuando el handler se espera con await para los eventos de herramientas, sin el error de serialización de la coroutine ni reintentos de invocación.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
With RestateAgent(..., event_stream_handler=<async fn>, auto_wrap_tools=True), the first tool call of a run fails the invocation with:
TypeError: Object of type coroutine is not JSON serializable
Text-only runs work fine — the crash only happens once the model calls a tool, because that's when wrapped_event_stream_handler journals tool-side events.
Environment
- restate-sdk 1.0.3 (bug also present on current
main) - pydantic-ai-slim 2.4.0
- Python 3.12, Restate server 1.7.2
Root cause
restate/ext/pydantic/_agent.py (line 171 on main), in wrapped_event_stream_handler:
await context.run_typed("run event", lambda: fn(ctx, single_event()))
fn is the user's event_stream_handler, which is an async function. The lambda wrapping it is a plain sync callable, so in server_context.create_run_coroutine:
if inspect.iscoroutinefunction(action): # False for the lambda
action_result = await action()
else:
...run in executor...
action_result = await action_result_future # <- the un-awaited coroutine object
buffer = serde.serialize(action_result) # TypeError: coroutine is not JSON serializable
The handler coroutine is never awaited (so the user's handler never runs for tool events), and Restate then tries to JSON-serialize the coroutine object itself.
Reproduction
import restate
from pydantic_ai import Agent
from restate.ext.pydantic import RestateAgent
agent = Agent("openai:gpt-4o")
@agent.tool_plain
def get_weather(city: str) -> str:
return "sunny"
svc = restate.Service("Repro")
@svc.handler()
async def run(ctx: restate.Context, prompt: str) -> str:
async def on_events(run_ctx, events):
async for _ in events:
pass
ragent = RestateAgent(agent, event_stream_handler=on_events, auto_wrap_tools=True)
result = await ragent.run(prompt)
return result.output
app = restate.app([svc])
Invoke with a prompt that triggers the tool, e.g. "What's the weather in Hanoi? Use the tool." → the run event journal entry fails with the TypeError above and the invocation retries forever.
Traceback
File ".../restate/server_context.py", line 857, in create_run_coroutine
buffer = serde.serialize(action_result)
File ".../restate/serde.py", line 317, in serialize
return json.dumps(obj).encode("utf-8")
...
TypeError: Object of type coroutine is not JSON serializable
Suggested fix
Use an async closure so create_run_coroutine awaits it:
async for event in stream:
async def single_event():
yield event
async def deliver() -> None:
await fn(ctx, single_event())
await context.run_typed("run event", deliver)
Related
- Found together with a second streaming+tools bug (turnstile never initialized in
request_stream), reported separately. - #201 fixed an earlier crash on this same streaming path — this combination (streaming handler +
auto_wrap_tools+ an actual tool call) seems to not be covered by tests yet.
- Lenguaje dominante
- Python
- Estrellas
- 81
- Forks
- 22
- Merge medio
- 2 d 2 h
- PR fusionados (30 d)
- 2
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de restatedev/sdk-python
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
restatedev/sdk-python#223 · 1 comentario ·
-
Dificultad 2/5 1-2 días Aptitud para principiantes 68/100
restatedev/sdk-python#204 · 1 comentario ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
restatedev/sdk-python#225 ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
restatedev/sdk-python#221 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 38/100
restatedev/sdk-python#205 · 1 comentario ·
Todos los issues de restatedev/sdk-python
Issues similares
-
货币战争手改优先级配置缺少列表元素类型校验(P3) Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
syfoud/Simulated_Scepter#172 ·
-
A cancelled tests run makes the coverage comment workflow fail and reports it as a red check on main Abiertoarea: ci bug perceived difficulty: 3
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Nitjsefnie-Harness-Commons/daedalus#921 · 1 comentario ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
EleutherAI/lm-evaluation-harness#4207 ·
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
ClickHouse/clickhouse-connect#1057 ·