agent-harness-bridge 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.
- agent_harness_bridge-0.1.0/LICENSE +21 -0
- agent_harness_bridge-0.1.0/PKG-INFO +154 -0
- agent_harness_bridge-0.1.0/README.md +99 -0
- agent_harness_bridge-0.1.0/agent_harness_bridge.egg-info/PKG-INFO +154 -0
- agent_harness_bridge-0.1.0/agent_harness_bridge.egg-info/SOURCES.txt +19 -0
- agent_harness_bridge-0.1.0/agent_harness_bridge.egg-info/dependency_links.txt +1 -0
- agent_harness_bridge-0.1.0/agent_harness_bridge.egg-info/requires.txt +23 -0
- agent_harness_bridge-0.1.0/agent_harness_bridge.egg-info/top_level.txt +1 -0
- agent_harness_bridge-0.1.0/harness_bridge/__init__.py +37 -0
- agent_harness_bridge-0.1.0/harness_bridge/_harness_claude.py +173 -0
- agent_harness_bridge-0.1.0/harness_bridge/_harness_deepseek.py +640 -0
- agent_harness_bridge-0.1.0/harness_bridge/_harness_host_tools.py +355 -0
- agent_harness_bridge-0.1.0/harness_bridge/_harness_openai.py +349 -0
- agent_harness_bridge-0.1.0/harness_bridge/harness.py +394 -0
- agent_harness_bridge-0.1.0/pyproject.toml +47 -0
- agent_harness_bridge-0.1.0/setup.cfg +4 -0
- agent_harness_bridge-0.1.0/tests/test_core.py +232 -0
- agent_harness_bridge-0.1.0/tests/test_deepseek_harness.py +103 -0
- agent_harness_bridge-0.1.0/tests/test_host_tools.py +129 -0
- agent_harness_bridge-0.1.0/tests/test_mcp_server_lifecycle.py +142 -0
- agent_harness_bridge-0.1.0/tests/test_openai_harness.py +287 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chansigit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-harness-bridge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small compatibility layer for OpenAI Agents SDK, Claude Agent SDK, and DeepSeek Harness
|
|
5
|
+
Author-email: chansigit <chansigit@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 chansigit
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/chansigit/agent-harness-bridge
|
|
29
|
+
Project-URL: Repository, https://github.com/chansigit/agent-harness-bridge
|
|
30
|
+
Project-URL: Issues, https://github.com/chansigit/agent-harness-bridge/issues
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
33
|
+
Requires-Python: >=3.10
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Provides-Extra: openai
|
|
37
|
+
Requires-Dist: openai-agents==0.22.0; extra == "openai"
|
|
38
|
+
Provides-Extra: claude
|
|
39
|
+
Requires-Dist: claude-agent-sdk>=0.2.152; extra == "claude"
|
|
40
|
+
Provides-Extra: deepseek
|
|
41
|
+
Requires-Dist: mcp<2,>=1.19; extra == "deepseek"
|
|
42
|
+
Requires-Dist: PyYAML>=6; extra == "deepseek"
|
|
43
|
+
Requires-Dist: uvicorn>=0.30; extra == "deepseek"
|
|
44
|
+
Requires-Dist: sse-starlette<4,>=3; extra == "deepseek"
|
|
45
|
+
Provides-Extra: all
|
|
46
|
+
Requires-Dist: openai-agents==0.22.0; extra == "all"
|
|
47
|
+
Requires-Dist: claude-agent-sdk>=0.2.152; extra == "all"
|
|
48
|
+
Requires-Dist: mcp<2,>=1.19; extra == "all"
|
|
49
|
+
Requires-Dist: PyYAML>=6; extra == "all"
|
|
50
|
+
Requires-Dist: uvicorn>=0.30; extra == "all"
|
|
51
|
+
Requires-Dist: sse-starlette<4,>=3; extra == "all"
|
|
52
|
+
Provides-Extra: test
|
|
53
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# Agent Harness Bridge
|
|
57
|
+
|
|
58
|
+
`agent-harness-bridge` gives applications one small, submit-tool-oriented API
|
|
59
|
+
for three different agent runtimes:
|
|
60
|
+
|
|
61
|
+
- OpenAI Agents SDK, including OpenAI-compatible endpoints such as Volcengine Ark
|
|
62
|
+
- Claude Agent SDK
|
|
63
|
+
- DeepSeek Harness (`dsh`)
|
|
64
|
+
|
|
65
|
+
It deliberately does not hide backend lifecycle differences. Each adapter owns
|
|
66
|
+
its native session continuation, MCP transport, timeout, cleanup and recovery
|
|
67
|
+
logic, while applications keep their prompts, domain tools and submit
|
|
68
|
+
validation.
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
Install only the runtime you need, or all validated adapters:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install 'agent-harness-bridge[openai]==0.1.0'
|
|
76
|
+
pip install 'agent-harness-bridge[claude]==0.1.0'
|
|
77
|
+
pip install 'agent-harness-bridge[deepseek]==0.1.0'
|
|
78
|
+
pip install 'agent-harness-bridge[all]==0.1.0'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The dsh adapter also imports `deepseek_harness`. DeepSeek's current SDK
|
|
82
|
+
depends on a platform-specific runtime wheel, so the bridge does not force
|
|
83
|
+
that wheel onto every installation. Install the SDK using the method supported
|
|
84
|
+
by the target host. On older-glibc clusters, load `polyfill-glibc/0.1` before
|
|
85
|
+
using its runtime or point `DSH_BIN` at a validated source build.
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Harness and model selection are independent:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
HARNESS=openai MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
93
|
+
HARNESS=openai MODEL=doubao-seed-2-1-pro-260628 python your_workflow.py
|
|
94
|
+
HARNESS=deepseek MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
95
|
+
HARNESS=claude MODEL=claude-sonnet-5 python your_workflow.py
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The default remains OpenAI Agents SDK with
|
|
99
|
+
`doubao-seed-2-1-turbo-260628`. Model identifiers are intentionally open
|
|
100
|
+
strings rather than a hard-coded catalog.
|
|
101
|
+
|
|
102
|
+
## Contract
|
|
103
|
+
|
|
104
|
+
Applications provide `ToolSpec` objects and designate one successful submit
|
|
105
|
+
tool as the completion condition:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from harness_bridge import ToolSpec, run_agent
|
|
109
|
+
|
|
110
|
+
async def submit(args):
|
|
111
|
+
return {
|
|
112
|
+
"content": [{"type": "text", "text": "accepted"}],
|
|
113
|
+
"_submitted": args,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
result = await run_agent(
|
|
117
|
+
tools=[ToolSpec("submit_answer", "Submit the checked answer", {"answer": str}, submit)],
|
|
118
|
+
submit_tool="submit_answer",
|
|
119
|
+
prompt="Check the evidence and submit the answer.",
|
|
120
|
+
cwd="/absolute/read-only/workdir",
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Tool handlers return an MCP-shaped result containing text or image content,
|
|
125
|
+
an optional `is_error`, and an optional private `_submitted` value captured by
|
|
126
|
+
the host after successful validation. A handler that raises is reported to
|
|
127
|
+
the model as an error result under every backend; it never aborts the run.
|
|
128
|
+
|
|
129
|
+
`run_agent()` validates the tool table before importing any SDK: the submit
|
|
130
|
+
tool must be present, tool names must be unique, `allowed_builtin` must be a
|
|
131
|
+
subset of `read`, `glob`, `grep`, `tasks`, and application tools may not
|
|
132
|
+
reuse the name of a requested builtin.
|
|
133
|
+
|
|
134
|
+
`allowed_builtin` selects Claude Code's own Read/Glob/Grep/Task tools under
|
|
135
|
+
`HARNESS=claude`. The OpenAI and dsh adapters serve same-named, cwd-confined
|
|
136
|
+
host tools implemented in pure Python (Grep needs no `rg` on the host), so
|
|
137
|
+
prompts stay portable across backends.
|
|
138
|
+
|
|
139
|
+
`backend_capabilities()` exposes runtime facts that callers can check before a
|
|
140
|
+
run. Unsupported built-in capabilities fail closed.
|
|
141
|
+
|
|
142
|
+
## Design boundary
|
|
143
|
+
|
|
144
|
+
The bridge owns only runtime concerns. Domain workflows should continue to own:
|
|
145
|
+
|
|
146
|
+
- prompts and scientific or business policy
|
|
147
|
+
- tool handler implementations
|
|
148
|
+
- submit validation
|
|
149
|
+
- output files and resume manifests
|
|
150
|
+
|
|
151
|
+
Backend-specific defenses remain adapter-local. In particular, OpenAI
|
|
152
|
+
Responses continuation and context reset, Claude SDK teardown and permissions,
|
|
153
|
+
and dsh MCP startup/watchdog/SSE recovery are not reduced to a lowest-common-
|
|
154
|
+
denominator loop.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Agent Harness Bridge
|
|
2
|
+
|
|
3
|
+
`agent-harness-bridge` gives applications one small, submit-tool-oriented API
|
|
4
|
+
for three different agent runtimes:
|
|
5
|
+
|
|
6
|
+
- OpenAI Agents SDK, including OpenAI-compatible endpoints such as Volcengine Ark
|
|
7
|
+
- Claude Agent SDK
|
|
8
|
+
- DeepSeek Harness (`dsh`)
|
|
9
|
+
|
|
10
|
+
It deliberately does not hide backend lifecycle differences. Each adapter owns
|
|
11
|
+
its native session continuation, MCP transport, timeout, cleanup and recovery
|
|
12
|
+
logic, while applications keep their prompts, domain tools and submit
|
|
13
|
+
validation.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
Install only the runtime you need, or all validated adapters:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install 'agent-harness-bridge[openai]==0.1.0'
|
|
21
|
+
pip install 'agent-harness-bridge[claude]==0.1.0'
|
|
22
|
+
pip install 'agent-harness-bridge[deepseek]==0.1.0'
|
|
23
|
+
pip install 'agent-harness-bridge[all]==0.1.0'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The dsh adapter also imports `deepseek_harness`. DeepSeek's current SDK
|
|
27
|
+
depends on a platform-specific runtime wheel, so the bridge does not force
|
|
28
|
+
that wheel onto every installation. Install the SDK using the method supported
|
|
29
|
+
by the target host. On older-glibc clusters, load `polyfill-glibc/0.1` before
|
|
30
|
+
using its runtime or point `DSH_BIN` at a validated source build.
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
Harness and model selection are independent:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
HARNESS=openai MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
38
|
+
HARNESS=openai MODEL=doubao-seed-2-1-pro-260628 python your_workflow.py
|
|
39
|
+
HARNESS=deepseek MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
40
|
+
HARNESS=claude MODEL=claude-sonnet-5 python your_workflow.py
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The default remains OpenAI Agents SDK with
|
|
44
|
+
`doubao-seed-2-1-turbo-260628`. Model identifiers are intentionally open
|
|
45
|
+
strings rather than a hard-coded catalog.
|
|
46
|
+
|
|
47
|
+
## Contract
|
|
48
|
+
|
|
49
|
+
Applications provide `ToolSpec` objects and designate one successful submit
|
|
50
|
+
tool as the completion condition:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from harness_bridge import ToolSpec, run_agent
|
|
54
|
+
|
|
55
|
+
async def submit(args):
|
|
56
|
+
return {
|
|
57
|
+
"content": [{"type": "text", "text": "accepted"}],
|
|
58
|
+
"_submitted": args,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
result = await run_agent(
|
|
62
|
+
tools=[ToolSpec("submit_answer", "Submit the checked answer", {"answer": str}, submit)],
|
|
63
|
+
submit_tool="submit_answer",
|
|
64
|
+
prompt="Check the evidence and submit the answer.",
|
|
65
|
+
cwd="/absolute/read-only/workdir",
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Tool handlers return an MCP-shaped result containing text or image content,
|
|
70
|
+
an optional `is_error`, and an optional private `_submitted` value captured by
|
|
71
|
+
the host after successful validation. A handler that raises is reported to
|
|
72
|
+
the model as an error result under every backend; it never aborts the run.
|
|
73
|
+
|
|
74
|
+
`run_agent()` validates the tool table before importing any SDK: the submit
|
|
75
|
+
tool must be present, tool names must be unique, `allowed_builtin` must be a
|
|
76
|
+
subset of `read`, `glob`, `grep`, `tasks`, and application tools may not
|
|
77
|
+
reuse the name of a requested builtin.
|
|
78
|
+
|
|
79
|
+
`allowed_builtin` selects Claude Code's own Read/Glob/Grep/Task tools under
|
|
80
|
+
`HARNESS=claude`. The OpenAI and dsh adapters serve same-named, cwd-confined
|
|
81
|
+
host tools implemented in pure Python (Grep needs no `rg` on the host), so
|
|
82
|
+
prompts stay portable across backends.
|
|
83
|
+
|
|
84
|
+
`backend_capabilities()` exposes runtime facts that callers can check before a
|
|
85
|
+
run. Unsupported built-in capabilities fail closed.
|
|
86
|
+
|
|
87
|
+
## Design boundary
|
|
88
|
+
|
|
89
|
+
The bridge owns only runtime concerns. Domain workflows should continue to own:
|
|
90
|
+
|
|
91
|
+
- prompts and scientific or business policy
|
|
92
|
+
- tool handler implementations
|
|
93
|
+
- submit validation
|
|
94
|
+
- output files and resume manifests
|
|
95
|
+
|
|
96
|
+
Backend-specific defenses remain adapter-local. In particular, OpenAI
|
|
97
|
+
Responses continuation and context reset, Claude SDK teardown and permissions,
|
|
98
|
+
and dsh MCP startup/watchdog/SSE recovery are not reduced to a lowest-common-
|
|
99
|
+
denominator loop.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-harness-bridge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small compatibility layer for OpenAI Agents SDK, Claude Agent SDK, and DeepSeek Harness
|
|
5
|
+
Author-email: chansigit <chansigit@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 chansigit
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/chansigit/agent-harness-bridge
|
|
29
|
+
Project-URL: Repository, https://github.com/chansigit/agent-harness-bridge
|
|
30
|
+
Project-URL: Issues, https://github.com/chansigit/agent-harness-bridge/issues
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
33
|
+
Requires-Python: >=3.10
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Provides-Extra: openai
|
|
37
|
+
Requires-Dist: openai-agents==0.22.0; extra == "openai"
|
|
38
|
+
Provides-Extra: claude
|
|
39
|
+
Requires-Dist: claude-agent-sdk>=0.2.152; extra == "claude"
|
|
40
|
+
Provides-Extra: deepseek
|
|
41
|
+
Requires-Dist: mcp<2,>=1.19; extra == "deepseek"
|
|
42
|
+
Requires-Dist: PyYAML>=6; extra == "deepseek"
|
|
43
|
+
Requires-Dist: uvicorn>=0.30; extra == "deepseek"
|
|
44
|
+
Requires-Dist: sse-starlette<4,>=3; extra == "deepseek"
|
|
45
|
+
Provides-Extra: all
|
|
46
|
+
Requires-Dist: openai-agents==0.22.0; extra == "all"
|
|
47
|
+
Requires-Dist: claude-agent-sdk>=0.2.152; extra == "all"
|
|
48
|
+
Requires-Dist: mcp<2,>=1.19; extra == "all"
|
|
49
|
+
Requires-Dist: PyYAML>=6; extra == "all"
|
|
50
|
+
Requires-Dist: uvicorn>=0.30; extra == "all"
|
|
51
|
+
Requires-Dist: sse-starlette<4,>=3; extra == "all"
|
|
52
|
+
Provides-Extra: test
|
|
53
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# Agent Harness Bridge
|
|
57
|
+
|
|
58
|
+
`agent-harness-bridge` gives applications one small, submit-tool-oriented API
|
|
59
|
+
for three different agent runtimes:
|
|
60
|
+
|
|
61
|
+
- OpenAI Agents SDK, including OpenAI-compatible endpoints such as Volcengine Ark
|
|
62
|
+
- Claude Agent SDK
|
|
63
|
+
- DeepSeek Harness (`dsh`)
|
|
64
|
+
|
|
65
|
+
It deliberately does not hide backend lifecycle differences. Each adapter owns
|
|
66
|
+
its native session continuation, MCP transport, timeout, cleanup and recovery
|
|
67
|
+
logic, while applications keep their prompts, domain tools and submit
|
|
68
|
+
validation.
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
Install only the runtime you need, or all validated adapters:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install 'agent-harness-bridge[openai]==0.1.0'
|
|
76
|
+
pip install 'agent-harness-bridge[claude]==0.1.0'
|
|
77
|
+
pip install 'agent-harness-bridge[deepseek]==0.1.0'
|
|
78
|
+
pip install 'agent-harness-bridge[all]==0.1.0'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The dsh adapter also imports `deepseek_harness`. DeepSeek's current SDK
|
|
82
|
+
depends on a platform-specific runtime wheel, so the bridge does not force
|
|
83
|
+
that wheel onto every installation. Install the SDK using the method supported
|
|
84
|
+
by the target host. On older-glibc clusters, load `polyfill-glibc/0.1` before
|
|
85
|
+
using its runtime or point `DSH_BIN` at a validated source build.
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Harness and model selection are independent:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
HARNESS=openai MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
93
|
+
HARNESS=openai MODEL=doubao-seed-2-1-pro-260628 python your_workflow.py
|
|
94
|
+
HARNESS=deepseek MODEL=doubao-seed-2-1-turbo-260628 python your_workflow.py
|
|
95
|
+
HARNESS=claude MODEL=claude-sonnet-5 python your_workflow.py
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The default remains OpenAI Agents SDK with
|
|
99
|
+
`doubao-seed-2-1-turbo-260628`. Model identifiers are intentionally open
|
|
100
|
+
strings rather than a hard-coded catalog.
|
|
101
|
+
|
|
102
|
+
## Contract
|
|
103
|
+
|
|
104
|
+
Applications provide `ToolSpec` objects and designate one successful submit
|
|
105
|
+
tool as the completion condition:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from harness_bridge import ToolSpec, run_agent
|
|
109
|
+
|
|
110
|
+
async def submit(args):
|
|
111
|
+
return {
|
|
112
|
+
"content": [{"type": "text", "text": "accepted"}],
|
|
113
|
+
"_submitted": args,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
result = await run_agent(
|
|
117
|
+
tools=[ToolSpec("submit_answer", "Submit the checked answer", {"answer": str}, submit)],
|
|
118
|
+
submit_tool="submit_answer",
|
|
119
|
+
prompt="Check the evidence and submit the answer.",
|
|
120
|
+
cwd="/absolute/read-only/workdir",
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Tool handlers return an MCP-shaped result containing text or image content,
|
|
125
|
+
an optional `is_error`, and an optional private `_submitted` value captured by
|
|
126
|
+
the host after successful validation. A handler that raises is reported to
|
|
127
|
+
the model as an error result under every backend; it never aborts the run.
|
|
128
|
+
|
|
129
|
+
`run_agent()` validates the tool table before importing any SDK: the submit
|
|
130
|
+
tool must be present, tool names must be unique, `allowed_builtin` must be a
|
|
131
|
+
subset of `read`, `glob`, `grep`, `tasks`, and application tools may not
|
|
132
|
+
reuse the name of a requested builtin.
|
|
133
|
+
|
|
134
|
+
`allowed_builtin` selects Claude Code's own Read/Glob/Grep/Task tools under
|
|
135
|
+
`HARNESS=claude`. The OpenAI and dsh adapters serve same-named, cwd-confined
|
|
136
|
+
host tools implemented in pure Python (Grep needs no `rg` on the host), so
|
|
137
|
+
prompts stay portable across backends.
|
|
138
|
+
|
|
139
|
+
`backend_capabilities()` exposes runtime facts that callers can check before a
|
|
140
|
+
run. Unsupported built-in capabilities fail closed.
|
|
141
|
+
|
|
142
|
+
## Design boundary
|
|
143
|
+
|
|
144
|
+
The bridge owns only runtime concerns. Domain workflows should continue to own:
|
|
145
|
+
|
|
146
|
+
- prompts and scientific or business policy
|
|
147
|
+
- tool handler implementations
|
|
148
|
+
- submit validation
|
|
149
|
+
- output files and resume manifests
|
|
150
|
+
|
|
151
|
+
Backend-specific defenses remain adapter-local. In particular, OpenAI
|
|
152
|
+
Responses continuation and context reset, Claude SDK teardown and permissions,
|
|
153
|
+
and dsh MCP startup/watchdog/SSE recovery are not reduced to a lowest-common-
|
|
154
|
+
denominator loop.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
agent_harness_bridge.egg-info/PKG-INFO
|
|
5
|
+
agent_harness_bridge.egg-info/SOURCES.txt
|
|
6
|
+
agent_harness_bridge.egg-info/dependency_links.txt
|
|
7
|
+
agent_harness_bridge.egg-info/requires.txt
|
|
8
|
+
agent_harness_bridge.egg-info/top_level.txt
|
|
9
|
+
harness_bridge/__init__.py
|
|
10
|
+
harness_bridge/_harness_claude.py
|
|
11
|
+
harness_bridge/_harness_deepseek.py
|
|
12
|
+
harness_bridge/_harness_host_tools.py
|
|
13
|
+
harness_bridge/_harness_openai.py
|
|
14
|
+
harness_bridge/harness.py
|
|
15
|
+
tests/test_core.py
|
|
16
|
+
tests/test_deepseek_harness.py
|
|
17
|
+
tests/test_host_tools.py
|
|
18
|
+
tests/test_mcp_server_lifecycle.py
|
|
19
|
+
tests/test_openai_harness.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
[all]
|
|
3
|
+
openai-agents==0.22.0
|
|
4
|
+
claude-agent-sdk>=0.2.152
|
|
5
|
+
mcp<2,>=1.19
|
|
6
|
+
PyYAML>=6
|
|
7
|
+
uvicorn>=0.30
|
|
8
|
+
sse-starlette<4,>=3
|
|
9
|
+
|
|
10
|
+
[claude]
|
|
11
|
+
claude-agent-sdk>=0.2.152
|
|
12
|
+
|
|
13
|
+
[deepseek]
|
|
14
|
+
mcp<2,>=1.19
|
|
15
|
+
PyYAML>=6
|
|
16
|
+
uvicorn>=0.30
|
|
17
|
+
sse-starlette<4,>=3
|
|
18
|
+
|
|
19
|
+
[openai]
|
|
20
|
+
openai-agents==0.22.0
|
|
21
|
+
|
|
22
|
+
[test]
|
|
23
|
+
pytest>=8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
harness_bridge
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Stable public API for the agent harness bridge."""
|
|
2
|
+
|
|
3
|
+
from .harness import (
|
|
4
|
+
AgentConfig,
|
|
5
|
+
AgentIncompleteError,
|
|
6
|
+
AgentLimitExhausted,
|
|
7
|
+
AgentRunResult,
|
|
8
|
+
AgentTimeout,
|
|
9
|
+
HarnessCapabilities,
|
|
10
|
+
ToolSpec,
|
|
11
|
+
backend_capabilities,
|
|
12
|
+
backend_name,
|
|
13
|
+
default_model,
|
|
14
|
+
resolve_agent_config,
|
|
15
|
+
retry_transient,
|
|
16
|
+
run_agent,
|
|
17
|
+
wall_seconds,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AgentConfig",
|
|
22
|
+
"AgentIncompleteError",
|
|
23
|
+
"AgentLimitExhausted",
|
|
24
|
+
"AgentRunResult",
|
|
25
|
+
"AgentTimeout",
|
|
26
|
+
"HarnessCapabilities",
|
|
27
|
+
"ToolSpec",
|
|
28
|
+
"backend_capabilities",
|
|
29
|
+
"backend_name",
|
|
30
|
+
"default_model",
|
|
31
|
+
"resolve_agent_config",
|
|
32
|
+
"retry_transient",
|
|
33
|
+
"run_agent",
|
|
34
|
+
"wall_seconds",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
__version__ = "0.1.0"
|