Skip to content

Python: [Feature]: Document and test Python ChatClient concurrent-use contract #7654

Description

Description

Please define and document whether Python ChatClient instances are safe to reuse across concurrent async calls, including mixed streaming and non-streaming calls.

Long-lived hosts such as Azure Functions need to reuse SDK clients and their HTTP connection pools across invocations to avoid connection churn and SNAT exhaustion. That means one OpenAIChatClient or FoundryChatClient wrapper may serve multiple fresh Agent/AgentSession instances concurrently. Today, the Python API documentation does not state whether this is supported or which objects must remain request-scoped.

The expected contract would clarify:

  • whether one OpenAIChatClient / FoundryChatClient can be shared by simultaneous Agent.run() calls;
  • whether streaming + streaming, non-streaming + non-streaming, and mixed streaming/non-streaming use are supported;
  • that messages, function-call IDs/arguments, middleware state, sessions, and stream events remain isolated per call;
  • whether the guarantee is limited to async tasks on one event loop or also covers OS threads/event loops;
  • which mutable extensions (for example middleware) are excluded from the guarantee.

A framework-level concurrency regression test for the supported combinations would make this contract durable.

In Azure/azure-functions-agents-runtime#158 we inspected Agent Framework Python 1.3 and added deterministic characterization tests using the real wrappers over a mock OpenAI Responses transport. Those tests show overlapping calls remain isolated for both wrappers across all three combinations, including distinct streamed function-call IDs. This gives us confidence in the pinned version, but it is not a substitute for an upstream compatibility guarantee.

Alternative considered: create a fresh ChatClient wrapper per invocation while sharing only the underlying HTTP transport. That avoids relying on wrapper concurrency but couples hosts to private transport ownership and defeats some of the intended SDK-client reuse model.

Code Sample

client = OpenAIChatClient(async_client=shared_async_openai, model="model")

# Each request gets fresh mutable Agent/session state while sharing the ChatClient.
first = Agent(client)
second = Agent(client)
await asyncio.gather(
    first.run("first", session=first.create_session()),
    second.run("second", stream=True, session=second.create_session()).get_final_response(),
)

Language/SDK

Python

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

documentationUsage: [Issues, PRs], Target: documentation in the code base and learn docspythonUsage: [Issues, PRs], Target: Python

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions