Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion python/.github/skills/python-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ from agent_framework.azure import AzureOpenAIChatClient

## Public API and Exports

Define `__all__` in each module. Avoid `from module import *` in `__init__.py` files:
In `__init__.py` files that define package-level public APIs, use direct re-export imports plus an explicit
`__all__`. Avoid identity aliases like `from ._agents import ChatAgent as ChatAgent`, and avoid
`from module import *`.

Do not define `__all__` in internal non-`__init__.py` modules. Exception: modules intentionally exposed as a
public import surface (for example, `agent_framework.observability`) should define `__all__`.

```python
__all__ = ["ChatAgent", "Message", "ChatResponse"]
Expand Down
47 changes: 19 additions & 28 deletions python/CODING_STANDARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,27 +130,6 @@ user_msg = UserMessage(content="Hello, world!")
asst_msg = AssistantMessage(content="Hello, world!")
```

### Logging

Use the centralized logging system:

```python
from agent_framework import get_logger

# For main package
logger = get_logger()

# For subpackages
logger = get_logger('agent_framework.azure')
```

**Do not use** direct logging module imports:
```python
# ❌ Avoid this
import logging
logger = logging.getLogger(__name__)
```

### Import Structure

The package follows a flat import structure:
Expand Down Expand Up @@ -189,8 +168,6 @@ python/
│ │ ├── _clients.py # Chat client protocols and base classes
│ │ ├── _tools.py # Tool definitions
│ │ ├── _types.py # Type definitions
│ │ ├── _logging.py # Logging utilities
│ │ │
│ │ │ # Provider folders - lazy load from connector packages
│ │ ├── openai/ # OpenAI clients (built into core)
│ │ ├── azure/ # Lazy loads from azure-ai, azure-ai-search, azurefunctions
Expand Down Expand Up @@ -405,12 +382,15 @@ If in doubt, use the link above to read much more considerations of what to do a

**All wildcard imports (`from ... import *`) are prohibited** in production code, including both `.py` and `.pyi` files. Always use explicit import lists to maintain clarity and avoid namespace pollution.

Define `__all__` in each module to explicitly declare the public API, then import specific symbols by name:
Do not use ``__all__`` in internal modules. Define it in the ``__init__`` file of the level you want to expose.
If a non-``__init__`` module is intentionally part of the public API surface (for example, ``observability.py``),
it should define ``__all__`` as well.

Also avoid identity alias imports in ``__init__`` files. Use ``from ._module import Symbol`` instead of
``from ._module import Symbol as Symbol``.

```python
# ✅ Preferred - explicit __all__ and named imports
__all__ = ["Agent", "Message", "ChatResponse"]

from ._agents import Agent
from ._types import Message, ChatResponse

Expand All @@ -422,9 +402,20 @@ from ._types import (
ResponseStream,
)

__all__ = [
"Agent",
"AgentResponse",
"ChatResponse",
"Message",
"ResponseStream",
]

# ❌ Prohibited pattern: wildcard/star imports (do not use)
# from ._agents import <all public symbols>
# from ._types import <all public symbols>
# from ._agents import *
# from ._types import *

# ❌ Prohibited pattern: identity alias imports (do not use)
# from ._agents import Agent as Agent
```

**Rationale:**
Expand Down
7 changes: 4 additions & 3 deletions python/packages/a2a/agent_framework_a2a/_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
normalize_messages,
prepend_agent_framework_to_user_agent,
)
from agent_framework._types import AgentRunInputs
from agent_framework.observability import AgentTelemetryLayer

__all__ = ["A2AAgent", "A2AContinuationToken"]
Expand Down Expand Up @@ -208,7 +209,7 @@ async def __aexit__(
@overload
def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: AgentRunInputs | None = None,
*,
stream: Literal[False] = ...,
session: AgentSession | None = None,
Expand All @@ -220,7 +221,7 @@ def run(
@overload
def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: AgentRunInputs | None = None,
*,
stream: Literal[True],
session: AgentSession | None = None,
Expand All @@ -231,7 +232,7 @@ def run(

def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: AgentRunInputs | None = None,
*,
stream: bool = False,
session: AgentSession | None = None,
Expand Down
8 changes: 1 addition & 7 deletions python/packages/ag-ui/agent_framework_ag_ui/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

from ._types import AGUIChatOptions

logger: logging.Logger = logging.getLogger(__name__)
logger: logging.Logger = logging.getLogger("agent_framework.ag_ui")


def _unwrap_server_function_call_contents(contents: MutableSequence[Content | dict[str, Any]]) -> None:
Expand Down Expand Up @@ -277,9 +277,6 @@ def _register_server_tool_placeholder(self, tool_name: str) -> None:
registered: set[str] = getattr(self, "_registered_server_tools", set())
registered.add(tool_name)
self._registered_server_tools = registered # type: ignore[attr-defined]
from agent_framework._logging import get_logger

logger = get_logger()
logger.debug(f"[AGUIChatClient] Registered server placeholder: {tool_name}")

def _extract_state_from_messages(self, messages: Sequence[Message]) -> tuple[list[Message], dict[str, Any] | None]:
Expand Down Expand Up @@ -310,9 +307,6 @@ def _extract_state_from_messages(self, messages: Sequence[Message]) -> tuple[lis
messages_without_state = list(messages[:-1]) if len(messages) > 1 else []
return messages_without_state, state
except (json.JSONDecodeError, ValueError, KeyError) as e:
from agent_framework._logging import get_logger

logger = get_logger()
logger.warning(f"Failed to extract state from message: {e}")

return list(messages), None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,6 @@ def _filter_modified_args(
approval_payload_text = result_content if isinstance(result_content, str) else json.dumps(parsed)

# Log the full approval payload to debug modified arguments
import logging

logger = logging.getLogger(__name__)
logger.info(f"Approval payload received: {parsed}")

approval_call_id = tool_call_id
Expand Down
4 changes: 2 additions & 2 deletions python/packages/ag-ui/getting_started/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import os
from typing import cast

from agent_framework import ChatResponse, ChatResponseUpdate, ResponseStream
from agent_framework import ChatResponse, ChatResponseUpdate, Message, ResponseStream
from agent_framework.ag_ui import AGUIChatClient


Expand Down Expand Up @@ -44,7 +44,7 @@ async def main():
metadata = {"thread_id": thread_id} if thread_id else None

stream = client.get_response(
message,
[Message(role="user", text=message)],
stream=True,
options={"metadata": metadata} if metadata else None,
)
Expand Down
18 changes: 11 additions & 7 deletions python/packages/ag-ui/getting_started/client_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import os
from typing import cast

from agent_framework import ChatResponse, ChatResponseUpdate, ResponseStream, tool
from agent_framework import ChatResponse, ChatResponseUpdate, Message, ResponseStream, tool
from agent_framework.ag_ui import AGUIChatClient


Expand Down Expand Up @@ -73,7 +73,7 @@ async def streaming_example(client: AGUIChatClient, thread_id: str | None = None
print("Assistant: ", end="", flush=True)

stream = client.get_response(
"Tell me a short joke",
[Message(role="user", text="Tell me a short joke")],
stream=True,
options={"metadata": metadata} if metadata else None,
)
Expand All @@ -100,7 +100,7 @@ async def non_streaming_example(client: AGUIChatClient, thread_id: str | None =

print("\nUser: What is 2 + 2?\n")

response = await client.get_response("What is 2 + 2?", metadata=metadata)
response = await client.get_response([Message(role="user", text="What is 2 + 2?")], metadata=metadata)

print(f"Assistant: {response.text}")

Expand Down Expand Up @@ -139,7 +139,7 @@ async def tool_example(client: AGUIChatClient, thread_id: str | None = None):
print("(Server must be configured with matching tools to execute them)\n")

response = await client.get_response(
"What's the weather in Seattle?", tools=[get_weather, calculate], metadata=metadata
[Message(role="user", text="What's the weather in Seattle?")], tools=[get_weather, calculate], metadata=metadata
)

print(f"Assistant: {response.text}")
Expand Down Expand Up @@ -174,14 +174,16 @@ async def conversation_example(client: AGUIChatClient):

# First turn
print("User: My name is Alice\n")
response1 = await client.get_response("My name is Alice")
response1 = await client.get_response([Message(role="user", text="My name is Alice")])
print(f"Assistant: {response1.text}")
thread_id = response1.additional_properties.get("thread_id")
print(f"\n[Thread: {thread_id}]")

# Second turn - using same thread
print("\nUser: What's my name?\n")
response2 = await client.get_response("What's my name?", options={"metadata": {"thread_id": thread_id}})
response2 = await client.get_response(
[Message(role="user", text="What's my name?")], options={"metadata": {"thread_id": thread_id}}
)
print(f"Assistant: {response2.text}")

# Check if context was maintained
Expand All @@ -191,7 +193,9 @@ async def conversation_example(client: AGUIChatClient):
# Third turn
print("\nUser: Can you also tell me what 10 * 5 is?\n")
response3 = await client.get_response(
"Can you also tell me what 10 * 5 is?", options={"metadata": {"thread_id": thread_id}}, tools=[calculate]
[Message(role="user", text="Can you also tell me what 10 * 5 is?")],
options={"metadata": {"thread_id": thread_id}},
tools=[calculate],
)
print(f"Assistant: {response3.text}")

Expand Down
14 changes: 7 additions & 7 deletions python/packages/ag-ui/tests/ag_ui/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, stream_fn: StreamFn, response_fn: ResponseFn | None = None) -
@overload
def get_response(
self,
messages: str | Message | Sequence[str | Message],
messages: Sequence[Message],
*,
stream: Literal[False] = ...,
options: ChatOptions[Any],
Expand All @@ -65,7 +65,7 @@ def get_response(
@overload
def get_response(
self,
messages: str | Message | Sequence[str | Message],
messages: Sequence[Message],
*,
stream: Literal[False] = ...,
options: OptionsCoT | ChatOptions[None] | None = ...,
Expand All @@ -75,7 +75,7 @@ def get_response(
@overload
def get_response(
self,
messages: str | Message | Sequence[str | Message],
messages: Sequence[Message],
*,
stream: Literal[True],
options: OptionsCoT | ChatOptions[Any] | None = ...,
Expand All @@ -84,7 +84,7 @@ def get_response(

def get_response(
self,
messages: str | Message | Sequence[str | Message],
messages: Sequence[Message],
*,
stream: bool = False,
options: OptionsCoT | ChatOptions[Any] | None = None,
Expand Down Expand Up @@ -175,7 +175,7 @@ def __init__(
@overload
def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: str | Content | Message | Sequence[str | Content | Message] | None = None,
*,
stream: Literal[False] = ...,
session: AgentSession | None = None,
Expand All @@ -185,7 +185,7 @@ def run(
@overload
def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: str | Content | Message | Sequence[str | Content | Message] | None = None,
*,
stream: Literal[True],
session: AgentSession | None = None,
Expand All @@ -194,7 +194,7 @@ def run(

def run(
self,
messages: str | Message | Sequence[str | Message] | None = None,
messages: str | Content | Message | Sequence[str | Content | Message] | None = None,
*,
stream: bool = False,
session: AgentSession | None = None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import logging
import sys
from collections.abc import AsyncIterable, Awaitable, Mapping, MutableMapping, Sequence
from typing import Any, ClassVar, Final, Generic, Literal, TypedDict
Expand All @@ -24,7 +25,6 @@
ResponseStream,
TextSpanRegion,
UsageDetails,
get_logger,
)
from agent_framework._settings import SecretString, load_settings
from agent_framework._types import _get_data_bytes_as_str # type: ignore
Expand Down Expand Up @@ -68,7 +68,7 @@
"ThinkingConfig",
]

logger = get_logger("agent_framework.anthropic")
logger = logging.getLogger("agent_framework.anthropic")

ANTHROPIC_DEFAULT_MAX_TOKENS: Final[int] = 1024
BETA_FLAGS: Final[list[str]] = ["mcp-client-2025-04-04", "code-execution-2025-08-25"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

from __future__ import annotations

import logging
import sys
from collections.abc import Awaitable, Callable
from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypedDict

from agent_framework import AGENT_FRAMEWORK_USER_AGENT, Message
from agent_framework._logging import get_logger
from agent_framework._sessions import AgentSession, BaseContextProvider, SessionContext
from agent_framework._settings import SecretString, load_settings
from agent_framework.exceptions import ServiceInitializationError
Expand Down Expand Up @@ -103,7 +103,7 @@
except ImportError:
_agentic_retrieval_available = False

logger = get_logger(__name__)
logger = logging.getLogger("agent_framework.azure_ai_search")

_DEFAULT_AGENTIC_MESSAGE_HISTORY_COUNT = 10

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import ast
import json
import logging
import os
import re
import sys
Expand Down Expand Up @@ -31,7 +32,6 @@
Role,
TextSpanRegion,
UsageDetails,
get_logger,
)
from agent_framework._settings import load_settings
from agent_framework.exceptions import ServiceInitializationError, ServiceInvalidRequestError, ServiceResponseException
Expand Down Expand Up @@ -102,7 +102,7 @@
from typing_extensions import Self, TypedDict # type: ignore # pragma: no cover


logger = get_logger("agent_framework.azure")
logger = logging.getLogger("agent_framework.azure")

__all__ = ["AzureAIAgentClient", "AzureAIAgentOptions"]

Expand Down
Loading