From 1ad8c9f270b051d9dd08421b0b488c7a99ce1ffa Mon Sep 17 00:00:00 2001 From: Amit Gazal Date: Thu, 23 Jul 2026 15:40:09 +0300 Subject: [PATCH 1/2] fix(examples): use ephemeral ports for Parlant servers [INT-530] Parlant's in-process server binds a fixed default port, so starting a second Parlant agent on the same machine fails when the first still holds the port. Pass port=0 and tool_service_port=0 in the example servers so the OS assigns free ports, letting agents like Tom and Jerry run side by side. Document the two-terminal multi-agent run in the README. Co-Authored-By: Claude Opus 4.8 (1M context) --- examples/parlant/01_basic_agent.py | 6 +++++- examples/parlant/02_with_guidelines.py | 6 +++++- examples/parlant/03_support_agent.py | 6 +++++- examples/parlant/04_tom_agent.py | 6 +++++- examples/parlant/05_jerry_agent.py | 6 +++++- examples/parlant/README.md | 14 ++++++++++++++ 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/examples/parlant/01_basic_agent.py b/examples/parlant/01_basic_agent.py index ca9579a64..520ead718 100644 --- a/examples/parlant/01_basic_agent.py +++ b/examples/parlant/01_basic_agent.py @@ -124,7 +124,11 @@ async def main() -> None: if not rest_url: raise ValueError("BAND_REST_URL environment variable is required") # Start Parlant server with OpenAI (requires OPENAI_API_KEY env var) - async with p.Server(nlp_service=p.NLPServices.openai) as server: + async with p.Server( + port=0, + tool_service_port=0, + nlp_service=p.NLPServices.openai, + ) as server: # Create Parlant tools INSIDE server context parlant_tools = create_parlant_tools() logger.info( diff --git a/examples/parlant/02_with_guidelines.py b/examples/parlant/02_with_guidelines.py index c4f13732a..7e5355bee 100644 --- a/examples/parlant/02_with_guidelines.py +++ b/examples/parlant/02_with_guidelines.py @@ -143,7 +143,11 @@ async def main() -> None: if not rest_url: raise ValueError("BAND_REST_URL environment variable is required") # Start Parlant server with OpenAI - async with p.Server(nlp_service=p.NLPServices.openai) as server: + async with p.Server( + port=0, + tool_service_port=0, + nlp_service=p.NLPServices.openai, + ) as server: # Create Parlant tools INSIDE server context parlant_tools = create_parlant_tools() logger.info( diff --git a/examples/parlant/03_support_agent.py b/examples/parlant/03_support_agent.py index d0b8bcbee..213503873 100644 --- a/examples/parlant/03_support_agent.py +++ b/examples/parlant/03_support_agent.py @@ -107,7 +107,11 @@ async def main() -> None: if not rest_url: raise ValueError("BAND_REST_URL environment variable is required") # Start Parlant server - async with p.Server(nlp_service=p.NLPServices.openai) as server: + async with p.Server( + port=0, + tool_service_port=0, + nlp_service=p.NLPServices.openai, + ) as server: # Create support agent with guidelines parlant_agent = await setup_support_agent(server) logger.info("Support agent created: %s", parlant_agent.id) diff --git a/examples/parlant/04_tom_agent.py b/examples/parlant/04_tom_agent.py index 6e2e057d9..b63b471b6 100644 --- a/examples/parlant/04_tom_agent.py +++ b/examples/parlant/04_tom_agent.py @@ -52,7 +52,11 @@ async def main() -> None: raise ValueError("BAND_REST_URL environment variable is required") # Load Tom's credentials from agent_config.yaml - async with p.Server(nlp_service=p.NLPServices.openai) as server: + async with p.Server( + port=0, + tool_service_port=0, + nlp_service=p.NLPServices.openai, + ) as server: parlant_tools = create_parlant_tools() # Create Parlant agent with Tom's personality diff --git a/examples/parlant/05_jerry_agent.py b/examples/parlant/05_jerry_agent.py index 251a750cc..5429569f4 100644 --- a/examples/parlant/05_jerry_agent.py +++ b/examples/parlant/05_jerry_agent.py @@ -52,7 +52,11 @@ async def main() -> None: raise ValueError("BAND_REST_URL environment variable is required") # Load Jerry's credentials from agent_config.yaml - async with p.Server(nlp_service=p.NLPServices.openai) as server: + async with p.Server( + port=0, + tool_service_port=0, + nlp_service=p.NLPServices.openai, + ) as server: parlant_tools = create_parlant_tools() # Create Parlant agent with Jerry's personality diff --git a/examples/parlant/README.md b/examples/parlant/README.md index 64f162da1..ab9208f2b 100644 --- a/examples/parlant/README.md +++ b/examples/parlant/README.md @@ -146,6 +146,20 @@ uv run python examples/parlant/03_support_agent.py > **Note:** The config loader looks for `agent_config.yaml` in the current working directory. Running from a subdirectory will cause a `FileNotFoundError`. +### Running two agents locally (Tom and Jerry) + +Each Parlant agent starts its own in-process server. The examples pass +`port=0` and `tool_service_port=0` so the OS assigns free ports, which lets +several agents run side by side without colliding on a fixed default port: + +```bash +# terminal 1 +uv run python examples/parlant/04_tom_agent.py + +# terminal 2 (while Tom is still running) +uv run python examples/parlant/05_jerry_agent.py +``` + --- ## Adapter Options From 3533aff2380375d82e2abf9bad42282b0486364a Mon Sep 17 00:00:00 2001 From: Amit Gazal Date: Thu, 23 Jul 2026 16:28:01 +0300 Subject: [PATCH 2/2] fix(deps): allow prerelease opentelemetry-resourcedetector-gcp A fresh, lockfile-free install of the google_adk / dev extras fails to resolve: google-adk pulls opentelemetry-exporter-gcp-trace, which only depends on prerelease (alpha) builds of opentelemetry-resourcedetector-gcp. Plain installs exclude prereleases by default, and the sole stable build (1.13.0) was yanked upstream ("breaks imports"), so there is no solution -- which breaks the packaging CI job's "install with all extras" step. Declare opentelemetry-resourcedetector-gcp directly with a prerelease specifier so the resolver may pick the alpha on a plain install, matching what the lockfile already used. Co-Authored-By: Claude Opus 4.8 (1M context) --- pyproject.toml | 9 +++++++++ uv.lock | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 955438657..8bb27c6ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -137,6 +137,12 @@ agentcore_runtime = [ ] google_adk = [ "google-adk>=1.0.0,<2", + # google-adk pulls opentelemetry-exporter-gcp-trace, which only depends on + # pre-release (alpha) builds of opentelemetry-resourcedetector-gcp. A plain + # install excludes pre-releases by default and the one stable build (1.13.0) + # was yanked upstream, leaving no solution — so request it explicitly with a + # pre-release specifier to allow the alpha. + "opentelemetry-resourcedetector-gcp>=1.11.0a0", ] agno = [ "agno>=2.6.0", @@ -194,6 +200,9 @@ dev = [ "google-genai>=1.43.0", # Include google-adk for testing "google-adk>=1.0.0,<2", + # See the google_adk extra: force the pre-release resourcedetector build so + # a plain (non-locked) install of this extra can resolve. + "opentelemetry-resourcedetector-gcp>=1.11.0a0", # Include Agno for testing "agno>=2.6.0", # Include letta-client for testing diff --git a/uv.lock b/uv.lock index eb0a8110e..0754267dc 100644 --- a/uv.lock +++ b/uv.lock @@ -602,6 +602,7 @@ dev = [ { name = "letta-client" }, { name = "mcp" }, { name = "openai" }, + { name = "opentelemetry-resourcedetector-gcp" }, { name = "parlant" }, { name = "pre-commit" }, { name = "pydantic-ai-slim" }, @@ -649,6 +650,7 @@ gemini = [ ] google-adk = [ { name = "google-adk" }, + { name = "opentelemetry-resourcedetector-gcp" }, ] langgraph = [ { name = "beautifulsoup4" }, @@ -763,6 +765,8 @@ requires-dist = [ { name = "openai", marker = "extra == 'langgraph'", specifier = ">=2.0.0" }, { name = "openai", marker = "extra == 'parlant'", specifier = ">=2.0.0" }, { name = "openai", marker = "extra == 'pydantic-ai'", specifier = ">=2.0.0" }, + { name = "opentelemetry-resourcedetector-gcp", marker = "extra == 'dev'", specifier = ">=1.11.0a0" }, + { name = "opentelemetry-resourcedetector-gcp", marker = "extra == 'google-adk'", specifier = ">=1.11.0a0" }, { name = "parlant", marker = "extra == 'dev'", specifier = ">=3.3.2" }, { name = "parlant", marker = "extra == 'parlant'", specifier = ">=3.3.2" }, { name = "phoenix-channels-python-client", specifier = ">=0.2.2" },