copass-google-agents 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copass_google_agents-0.1.0/.gitignore +38 -0
- copass_google_agents-0.1.0/PKG-INFO +138 -0
- copass_google_agents-0.1.0/README.md +114 -0
- copass_google_agents-0.1.0/pyproject.toml +60 -0
- copass_google_agents-0.1.0/src/copass_google_agents/__init__.py +104 -0
- copass_google_agents-0.1.0/src/copass_google_agents/_proxy_tool.py +101 -0
- copass_google_agents-0.1.0/src/copass_google_agents/backends/__init__.py +23 -0
- copass_google_agents-0.1.0/src/copass_google_agents/backends/google_agent_backend.py +413 -0
- copass_google_agents-0.1.0/src/copass_google_agents/deploy.py +201 -0
- copass_google_agents-0.1.0/src/copass_google_agents/events.py +143 -0
- copass_google_agents-0.1.0/src/copass_google_agents/google_agent.py +151 -0
- copass_google_agents-0.1.0/tests/test_deploy.py +164 -0
- copass_google_agents-0.1.0/tests/test_events.py +258 -0
- copass_google_agents-0.1.0/tests/test_google_agent_backend.py +390 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
*.tsbuildinfo
|
|
7
|
+
|
|
8
|
+
# Environment
|
|
9
|
+
.env
|
|
10
|
+
.env.*
|
|
11
|
+
|
|
12
|
+
# IDE
|
|
13
|
+
.vscode/
|
|
14
|
+
.idea/
|
|
15
|
+
*.swp
|
|
16
|
+
*.swo
|
|
17
|
+
*~
|
|
18
|
+
|
|
19
|
+
# OS
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
|
|
23
|
+
# Test
|
|
24
|
+
coverage/
|
|
25
|
+
|
|
26
|
+
# Lerna
|
|
27
|
+
lerna-debug.log
|
|
28
|
+
.nx/cache
|
|
29
|
+
.nx/workspace-data
|
|
30
|
+
|
|
31
|
+
# Python
|
|
32
|
+
__pycache__/
|
|
33
|
+
*.pyc
|
|
34
|
+
*.pyo
|
|
35
|
+
*.egg-info/
|
|
36
|
+
.venv/
|
|
37
|
+
venv/
|
|
38
|
+
.olane
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: copass-google-agents
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Copass agent primitives for Google Vertex AI Agent Engine (ADK)
|
|
5
|
+
Project-URL: Homepage, https://github.com/olane-labs/copass-harness
|
|
6
|
+
Project-URL: Repository, https://github.com/olane-labs/copass-harness.git
|
|
7
|
+
Author: Olane Inc.
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: adk,agent-engine,agents,copass,google,knowledge-graph,vertex-ai
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: copass-core-agents>=0.1.0
|
|
17
|
+
Requires-Dist: google-cloud-aiplatform[adk,agent-engines]>=1.148.1
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# copass-google-agents
|
|
26
|
+
|
|
27
|
+
Google Vertex AI **Agent Engine** (ADK) backend for Copass. Depends on [`copass-core-agents`](../copass-core-agents), which owns the vendor-neutral primitives (`BaseAgent`, `AgentTool`, `AgentBackend` ABC, events, `AgentScope`, registries, etc.) shared across every provider-specific Copass SDK.
|
|
28
|
+
|
|
29
|
+
This package owns the Google-specific piece — `GoogleAgentBackend` and the `CopassGoogleAgent` convenience subclass — and re-exports the core primitives for one-line dev imports. Either of these works for consumers:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from copass_google_agents import BaseAgent, CopassGoogleAgent # convenient
|
|
33
|
+
# or
|
|
34
|
+
from copass_core_agents import BaseAgent # explicit boundary
|
|
35
|
+
from copass_google_agents import CopassGoogleAgent
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Pairs with Copass's server-side router — both sides import the same code so the agent runtime is a single codepath, whether the agent runs in the dev's process or server-side via Copass's Router endpoint.
|
|
39
|
+
|
|
40
|
+
> **Status: scaffold (v0.1.0).** Constructors, type surface, and public imports are in place. `GoogleAgentBackend.run` / `GoogleAgentBackend.stream` / `deploy_adk_agent` / `adk_event_to_agent_events` currently raise `NotImplementedError`. Implementation lands in a follow-up pass.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install copass-google-agents
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Requires `google-cloud-aiplatform[agent_engines,adk]>=1.148.1` (which pulls in `google-adk>=1.31`). Uses Application Default Credentials (ADC) — run `gcloud auth application-default login` locally, or set `GOOGLE_APPLICATION_CREDENTIALS` / attach a service account.
|
|
49
|
+
|
|
50
|
+
## Architecture
|
|
51
|
+
|
|
52
|
+
Agent Engine diverges from Claude Managed Agents in one important way: **ADK agents are pre-deployed resources** (`projects/{p}/locations/{l}/reasoningEngines/{id}`) and their **tools are baked in at deploy time**. You cannot pass tools per-run.
|
|
53
|
+
|
|
54
|
+
To preserve Copass's `AgentToolResolver` runtime-plug model, `copass-google-agents` deploys ADK agents carrying a single `copass_dispatch(tool_name, arguments)` function tool. At run time that proxy calls back into your Copass service, which hosts the real resolver and invokes the right tool for the current user.
|
|
55
|
+
|
|
56
|
+
So:
|
|
57
|
+
- **`GoogleAgentBackend`** is *session-only* — streams queries against a pre-deployed engine.
|
|
58
|
+
- **`deploy_adk_agent`** (ops helper) is the one-time setup that wires the proxy tool into a new ADK agent resource.
|
|
59
|
+
- **Zero client-side tools** is the expected case. `CopassGoogleAgent` defaults to an empty `AgentToolRegistry`.
|
|
60
|
+
|
|
61
|
+
## Quickstart (planned — not functional in the scaffold)
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import os
|
|
65
|
+
from copass_google_agents import (
|
|
66
|
+
AgentInvocationContext,
|
|
67
|
+
AgentScope,
|
|
68
|
+
CopassGoogleAgent,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
agent = CopassGoogleAgent(
|
|
72
|
+
identity="support",
|
|
73
|
+
system_prompt="You are a support agent.",
|
|
74
|
+
project=os.environ["GOOGLE_CLOUD_PROJECT"],
|
|
75
|
+
reasoning_engine_id=os.environ["COPASS_REASONING_ENGINE_ID"],
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
ctx = AgentInvocationContext(scope=AgentScope(user_id="u-123"))
|
|
79
|
+
result = await agent.run(
|
|
80
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
81
|
+
context=ctx,
|
|
82
|
+
)
|
|
83
|
+
print(result.final_text)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Streaming (planned)
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from copass_google_agents import (
|
|
90
|
+
AgentFinish,
|
|
91
|
+
AgentTextDelta,
|
|
92
|
+
AgentToolCall,
|
|
93
|
+
AgentToolResult,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
async for evt in agent.stream(messages, context=ctx):
|
|
97
|
+
match evt:
|
|
98
|
+
case AgentTextDelta(text=chunk):
|
|
99
|
+
print(chunk, end="", flush=True)
|
|
100
|
+
case AgentToolCall(name=name):
|
|
101
|
+
print(f"\n[tool-call] {name}")
|
|
102
|
+
case AgentToolResult(name=name):
|
|
103
|
+
print(f"\n[tool-result] {name}")
|
|
104
|
+
case AgentFinish(stop_reason=reason, session_id=sid):
|
|
105
|
+
print(f"\n[finish] {reason} session={sid}")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Multi-turn continuation (planned)
|
|
109
|
+
|
|
110
|
+
Agent Engine sessions hold conversation state. Capture `AgentFinish.session_id` and thread it back on the next turn:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from copass_google_agents import SESSION_ID_HANDLE
|
|
114
|
+
|
|
115
|
+
ctx2 = AgentInvocationContext(
|
|
116
|
+
scope=AgentScope(user_id="u-123"),
|
|
117
|
+
handles={SESSION_ID_HANDLE: prior_session_id},
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Deploying an ADK agent (planned)
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from copass_google_agents.deploy import deploy_adk_agent
|
|
125
|
+
|
|
126
|
+
engine = deploy_adk_agent(
|
|
127
|
+
display_name="support-agent",
|
|
128
|
+
project="my-gcp-project",
|
|
129
|
+
system_prompt="You are a support agent...",
|
|
130
|
+
copass_api_url="https://api.copass.id",
|
|
131
|
+
copass_api_key=os.environ["COPASS_API_KEY"],
|
|
132
|
+
)
|
|
133
|
+
print(engine.resource_name) # feed into CopassGoogleAgent(reasoning_engine_id=...)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# copass-google-agents
|
|
2
|
+
|
|
3
|
+
Google Vertex AI **Agent Engine** (ADK) backend for Copass. Depends on [`copass-core-agents`](../copass-core-agents), which owns the vendor-neutral primitives (`BaseAgent`, `AgentTool`, `AgentBackend` ABC, events, `AgentScope`, registries, etc.) shared across every provider-specific Copass SDK.
|
|
4
|
+
|
|
5
|
+
This package owns the Google-specific piece — `GoogleAgentBackend` and the `CopassGoogleAgent` convenience subclass — and re-exports the core primitives for one-line dev imports. Either of these works for consumers:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from copass_google_agents import BaseAgent, CopassGoogleAgent # convenient
|
|
9
|
+
# or
|
|
10
|
+
from copass_core_agents import BaseAgent # explicit boundary
|
|
11
|
+
from copass_google_agents import CopassGoogleAgent
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Pairs with Copass's server-side router — both sides import the same code so the agent runtime is a single codepath, whether the agent runs in the dev's process or server-side via Copass's Router endpoint.
|
|
15
|
+
|
|
16
|
+
> **Status: scaffold (v0.1.0).** Constructors, type surface, and public imports are in place. `GoogleAgentBackend.run` / `GoogleAgentBackend.stream` / `deploy_adk_agent` / `adk_event_to_agent_events` currently raise `NotImplementedError`. Implementation lands in a follow-up pass.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install copass-google-agents
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires `google-cloud-aiplatform[agent_engines,adk]>=1.148.1` (which pulls in `google-adk>=1.31`). Uses Application Default Credentials (ADC) — run `gcloud auth application-default login` locally, or set `GOOGLE_APPLICATION_CREDENTIALS` / attach a service account.
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
Agent Engine diverges from Claude Managed Agents in one important way: **ADK agents are pre-deployed resources** (`projects/{p}/locations/{l}/reasoningEngines/{id}`) and their **tools are baked in at deploy time**. You cannot pass tools per-run.
|
|
29
|
+
|
|
30
|
+
To preserve Copass's `AgentToolResolver` runtime-plug model, `copass-google-agents` deploys ADK agents carrying a single `copass_dispatch(tool_name, arguments)` function tool. At run time that proxy calls back into your Copass service, which hosts the real resolver and invokes the right tool for the current user.
|
|
31
|
+
|
|
32
|
+
So:
|
|
33
|
+
- **`GoogleAgentBackend`** is *session-only* — streams queries against a pre-deployed engine.
|
|
34
|
+
- **`deploy_adk_agent`** (ops helper) is the one-time setup that wires the proxy tool into a new ADK agent resource.
|
|
35
|
+
- **Zero client-side tools** is the expected case. `CopassGoogleAgent` defaults to an empty `AgentToolRegistry`.
|
|
36
|
+
|
|
37
|
+
## Quickstart (planned — not functional in the scaffold)
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import os
|
|
41
|
+
from copass_google_agents import (
|
|
42
|
+
AgentInvocationContext,
|
|
43
|
+
AgentScope,
|
|
44
|
+
CopassGoogleAgent,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
agent = CopassGoogleAgent(
|
|
48
|
+
identity="support",
|
|
49
|
+
system_prompt="You are a support agent.",
|
|
50
|
+
project=os.environ["GOOGLE_CLOUD_PROJECT"],
|
|
51
|
+
reasoning_engine_id=os.environ["COPASS_REASONING_ENGINE_ID"],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
ctx = AgentInvocationContext(scope=AgentScope(user_id="u-123"))
|
|
55
|
+
result = await agent.run(
|
|
56
|
+
messages=[{"role": "user", "content": "Hello"}],
|
|
57
|
+
context=ctx,
|
|
58
|
+
)
|
|
59
|
+
print(result.final_text)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Streaming (planned)
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from copass_google_agents import (
|
|
66
|
+
AgentFinish,
|
|
67
|
+
AgentTextDelta,
|
|
68
|
+
AgentToolCall,
|
|
69
|
+
AgentToolResult,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
async for evt in agent.stream(messages, context=ctx):
|
|
73
|
+
match evt:
|
|
74
|
+
case AgentTextDelta(text=chunk):
|
|
75
|
+
print(chunk, end="", flush=True)
|
|
76
|
+
case AgentToolCall(name=name):
|
|
77
|
+
print(f"\n[tool-call] {name}")
|
|
78
|
+
case AgentToolResult(name=name):
|
|
79
|
+
print(f"\n[tool-result] {name}")
|
|
80
|
+
case AgentFinish(stop_reason=reason, session_id=sid):
|
|
81
|
+
print(f"\n[finish] {reason} session={sid}")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Multi-turn continuation (planned)
|
|
85
|
+
|
|
86
|
+
Agent Engine sessions hold conversation state. Capture `AgentFinish.session_id` and thread it back on the next turn:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from copass_google_agents import SESSION_ID_HANDLE
|
|
90
|
+
|
|
91
|
+
ctx2 = AgentInvocationContext(
|
|
92
|
+
scope=AgentScope(user_id="u-123"),
|
|
93
|
+
handles={SESSION_ID_HANDLE: prior_session_id},
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Deploying an ADK agent (planned)
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from copass_google_agents.deploy import deploy_adk_agent
|
|
101
|
+
|
|
102
|
+
engine = deploy_adk_agent(
|
|
103
|
+
display_name="support-agent",
|
|
104
|
+
project="my-gcp-project",
|
|
105
|
+
system_prompt="You are a support agent...",
|
|
106
|
+
copass_api_url="https://api.copass.id",
|
|
107
|
+
copass_api_key=os.environ["COPASS_API_KEY"],
|
|
108
|
+
)
|
|
109
|
+
print(engine.resource_name) # feed into CopassGoogleAgent(reasoning_engine_id=...)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "copass-google-agents"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Copass agent primitives for Google Vertex AI Agent Engine (ADK)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Olane Inc." }]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
keywords = [
|
|
14
|
+
"copass",
|
|
15
|
+
"knowledge-graph",
|
|
16
|
+
"google",
|
|
17
|
+
"vertex-ai",
|
|
18
|
+
"agent-engine",
|
|
19
|
+
"adk",
|
|
20
|
+
"agents",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"google-cloud-aiplatform[agent_engines,adk]>=1.148.1",
|
|
31
|
+
"copass-core-agents>=0.1.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=8.0",
|
|
37
|
+
"pytest-asyncio>=0.23",
|
|
38
|
+
"mypy>=1.10",
|
|
39
|
+
"ruff>=0.5",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/olane-labs/copass-harness"
|
|
44
|
+
Repository = "https://github.com/olane-labs/copass-harness.git"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/copass_google_agents"]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
asyncio_mode = "auto"
|
|
51
|
+
testpaths = ["tests"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = "py310"
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
python_version = "3.10"
|
|
59
|
+
strict = true
|
|
60
|
+
packages = ["copass_google_agents"]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Copass agent SDK for Google Vertex AI Agent Engine (ADK).
|
|
2
|
+
|
|
3
|
+
This package owns the Google-specific backend. All provider-neutral
|
|
4
|
+
ABCs (``BaseAgent``, ``AgentTool``, ``AgentBackend``, events, scope,
|
|
5
|
+
registries) live in :mod:`copass_core_agents` and are re-exported here
|
|
6
|
+
for convenience — dev code can import everything it needs from one
|
|
7
|
+
place.
|
|
8
|
+
|
|
9
|
+
Public surface:
|
|
10
|
+
|
|
11
|
+
Google-specific (owned here):
|
|
12
|
+
GoogleAgentBackend
|
|
13
|
+
CopassGoogleAgent — convenience subclass of BaseAgent
|
|
14
|
+
DEFAULT_LOCATION
|
|
15
|
+
DEFAULT_MODEL
|
|
16
|
+
DISPATCH_TOOL_NAME
|
|
17
|
+
SESSION_ID_HANDLE
|
|
18
|
+
|
|
19
|
+
Provider-neutral (re-exported from copass_core_agents):
|
|
20
|
+
BaseAgent, AgentScope, AgentInvocationContext
|
|
21
|
+
AgentTool, AgentToolRegistry, AgentToolResolver
|
|
22
|
+
ToolSpec, ToolCall, ToolConflictPolicy, ToolConflictError
|
|
23
|
+
AgentEvent, AgentTextDelta, AgentToolCall, AgentToolResult,
|
|
24
|
+
AgentFinish
|
|
25
|
+
AgentBackend, AgentRunResult
|
|
26
|
+
register_agent, get_agent_class, list_agents
|
|
27
|
+
register_agent_tool, get_agent_tool, try_get_agent_tool,
|
|
28
|
+
list_agent_tools
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# Re-export core (vendor-neutral) primitives for one-line imports.
|
|
32
|
+
from copass_core_agents import (
|
|
33
|
+
AgentBackend,
|
|
34
|
+
AgentEvent,
|
|
35
|
+
AgentFinish,
|
|
36
|
+
AgentInvocationContext,
|
|
37
|
+
AgentRunResult,
|
|
38
|
+
AgentScope,
|
|
39
|
+
AgentTextDelta,
|
|
40
|
+
AgentTool,
|
|
41
|
+
AgentToolCall,
|
|
42
|
+
AgentToolRegistry,
|
|
43
|
+
AgentToolResolver,
|
|
44
|
+
AgentToolResult,
|
|
45
|
+
BaseAgent,
|
|
46
|
+
ToolCall,
|
|
47
|
+
ToolConflictError,
|
|
48
|
+
ToolConflictPolicy,
|
|
49
|
+
ToolSpec,
|
|
50
|
+
get_agent_class,
|
|
51
|
+
get_agent_tool,
|
|
52
|
+
list_agent_tools,
|
|
53
|
+
list_agents,
|
|
54
|
+
register_agent,
|
|
55
|
+
register_agent_tool,
|
|
56
|
+
try_get_agent_tool,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Google-specific (owned here).
|
|
60
|
+
from copass_google_agents.backends.google_agent_backend import (
|
|
61
|
+
DEFAULT_LOCATION,
|
|
62
|
+
DISPATCH_TOOL_NAME,
|
|
63
|
+
SESSION_ID_HANDLE,
|
|
64
|
+
GoogleAgentBackend,
|
|
65
|
+
)
|
|
66
|
+
from copass_google_agents.google_agent import DEFAULT_MODEL, CopassGoogleAgent
|
|
67
|
+
|
|
68
|
+
__version__ = "0.1.0"
|
|
69
|
+
|
|
70
|
+
__all__ = [
|
|
71
|
+
"__version__",
|
|
72
|
+
# Google-specific
|
|
73
|
+
"CopassGoogleAgent",
|
|
74
|
+
"DEFAULT_MODEL",
|
|
75
|
+
"GoogleAgentBackend",
|
|
76
|
+
"DEFAULT_LOCATION",
|
|
77
|
+
"DISPATCH_TOOL_NAME",
|
|
78
|
+
"SESSION_ID_HANDLE",
|
|
79
|
+
# Re-exported from copass_core_agents
|
|
80
|
+
"BaseAgent",
|
|
81
|
+
"AgentScope",
|
|
82
|
+
"AgentInvocationContext",
|
|
83
|
+
"AgentTool",
|
|
84
|
+
"AgentToolRegistry",
|
|
85
|
+
"AgentToolResolver",
|
|
86
|
+
"ToolSpec",
|
|
87
|
+
"ToolCall",
|
|
88
|
+
"ToolConflictError",
|
|
89
|
+
"ToolConflictPolicy",
|
|
90
|
+
"AgentEvent",
|
|
91
|
+
"AgentTextDelta",
|
|
92
|
+
"AgentToolCall",
|
|
93
|
+
"AgentToolResult",
|
|
94
|
+
"AgentFinish",
|
|
95
|
+
"AgentBackend",
|
|
96
|
+
"AgentRunResult",
|
|
97
|
+
"register_agent",
|
|
98
|
+
"get_agent_class",
|
|
99
|
+
"list_agents",
|
|
100
|
+
"register_agent_tool",
|
|
101
|
+
"get_agent_tool",
|
|
102
|
+
"try_get_agent_tool",
|
|
103
|
+
"list_agent_tools",
|
|
104
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Module-scope definition of the ``copass_dispatch`` proxy tool.
|
|
2
|
+
|
|
3
|
+
ADK serializes function tools by reference; closures over deploy-time
|
|
4
|
+
variables do not round-trip into Agent Engine's remote runtime.
|
|
5
|
+
This module defines the tool at module scope and reads its
|
|
6
|
+
configuration from environment variables baked into the deployed
|
|
7
|
+
engine (``COPASS_API_URL``, ``COPASS_API_KEY``, ``COPASS_DISPATCH_PATH``).
|
|
8
|
+
|
|
9
|
+
The function's signature and docstring are what ADK exposes to the
|
|
10
|
+
model as the tool schema — keep both pedagogical.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from typing import Any, Dict, Optional
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DEFAULT_DISPATCH_PATH = "/api/v1/agents/dispatch"
|
|
20
|
+
"""Default path on the Copass service where the proxy POSTs tool
|
|
21
|
+
invocations. Overridable at deploy time via ``COPASS_DISPATCH_PATH``."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def copass_dispatch(
|
|
25
|
+
tool_name: str,
|
|
26
|
+
arguments: Dict[str, Any],
|
|
27
|
+
tool_context: Optional[Any] = None,
|
|
28
|
+
) -> Dict[str, Any]:
|
|
29
|
+
"""Route a tool invocation through Copass's server-side resolver.
|
|
30
|
+
|
|
31
|
+
ADK Agent Engine bakes tools at deploy time. To preserve the
|
|
32
|
+
runtime ``AgentToolResolver`` plug model, every deployed Copass
|
|
33
|
+
agent carries exactly this one function tool. The model calls
|
|
34
|
+
``copass_dispatch`` with the logical tool name and arguments;
|
|
35
|
+
the Copass service receives the call, looks the tool up against
|
|
36
|
+
the current user's resolver, executes it, and returns the result.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
tool_name: The logical name of the tool to invoke (as
|
|
40
|
+
advertised in the agent's system prompt).
|
|
41
|
+
arguments: JSON-serializable arguments for the tool.
|
|
42
|
+
tool_context: ADK-injected context providing ``user_id`` and
|
|
43
|
+
``session_id`` when available. ADK populates this
|
|
44
|
+
automatically at invocation time.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
The tool result dict, passed straight from the Copass
|
|
48
|
+
service response body.
|
|
49
|
+
"""
|
|
50
|
+
import httpx # deferred import — keeps cold-start lean
|
|
51
|
+
|
|
52
|
+
api_url = os.environ.get("COPASS_API_URL")
|
|
53
|
+
api_key = os.environ.get("COPASS_API_KEY")
|
|
54
|
+
if not api_url or not api_key:
|
|
55
|
+
return {
|
|
56
|
+
"error": (
|
|
57
|
+
"copass_dispatch misconfigured: COPASS_API_URL / "
|
|
58
|
+
"COPASS_API_KEY env vars not set on the deployed agent."
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
path = os.environ.get("COPASS_DISPATCH_PATH", DEFAULT_DISPATCH_PATH)
|
|
62
|
+
|
|
63
|
+
user_id = None
|
|
64
|
+
session_id = None
|
|
65
|
+
if tool_context is not None:
|
|
66
|
+
user_id = getattr(tool_context, "user_id", None)
|
|
67
|
+
session_id = getattr(tool_context, "session_id", None)
|
|
68
|
+
|
|
69
|
+
payload = {
|
|
70
|
+
"tool_name": tool_name,
|
|
71
|
+
"arguments": arguments or {},
|
|
72
|
+
"user_id": user_id,
|
|
73
|
+
"session_id": session_id,
|
|
74
|
+
}
|
|
75
|
+
url = f"{api_url.rstrip('/')}{path}"
|
|
76
|
+
|
|
77
|
+
async with httpx.AsyncClient(timeout=60.0) as http:
|
|
78
|
+
resp = await http.post(
|
|
79
|
+
url,
|
|
80
|
+
json=payload,
|
|
81
|
+
headers={
|
|
82
|
+
"Authorization": f"Bearer {api_key}",
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
},
|
|
85
|
+
)
|
|
86
|
+
try:
|
|
87
|
+
resp.raise_for_status()
|
|
88
|
+
except httpx.HTTPStatusError as err:
|
|
89
|
+
return {
|
|
90
|
+
"error": (
|
|
91
|
+
f"copass_dispatch HTTP {resp.status_code}: {err}"
|
|
92
|
+
),
|
|
93
|
+
"response_text": resp.text[:1000],
|
|
94
|
+
}
|
|
95
|
+
try:
|
|
96
|
+
return dict(resp.json())
|
|
97
|
+
except ValueError:
|
|
98
|
+
return {"text": resp.text}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
__all__ = ["copass_dispatch", "DEFAULT_DISPATCH_PATH"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Google agent backends.
|
|
2
|
+
|
|
3
|
+
Re-exports the core ``AgentBackend`` / ``AgentRunResult`` ABCs
|
|
4
|
+
(implemented in ``copass-core-agents``) alongside this package's
|
|
5
|
+
Google-specific ``GoogleAgentBackend``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from copass_core_agents.backends import AgentBackend, AgentRunResult
|
|
9
|
+
from copass_google_agents.backends.google_agent_backend import (
|
|
10
|
+
DEFAULT_LOCATION,
|
|
11
|
+
DISPATCH_TOOL_NAME,
|
|
12
|
+
SESSION_ID_HANDLE,
|
|
13
|
+
GoogleAgentBackend,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AgentBackend",
|
|
18
|
+
"AgentRunResult",
|
|
19
|
+
"GoogleAgentBackend",
|
|
20
|
+
"DEFAULT_LOCATION",
|
|
21
|
+
"DISPATCH_TOOL_NAME",
|
|
22
|
+
"SESSION_ID_HANDLE",
|
|
23
|
+
]
|