agent-dna 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_dna-0.1.0/LICENSE +21 -0
- agent_dna-0.1.0/PKG-INFO +143 -0
- agent_dna-0.1.0/README.md +127 -0
- agent_dna-0.1.0/agent_dna.egg-info/PKG-INFO +143 -0
- agent_dna-0.1.0/agent_dna.egg-info/SOURCES.txt +14 -0
- agent_dna-0.1.0/agent_dna.egg-info/dependency_links.txt +1 -0
- agent_dna-0.1.0/agent_dna.egg-info/requires.txt +3 -0
- agent_dna-0.1.0/agent_dna.egg-info/top_level.txt +1 -0
- agent_dna-0.1.0/agentdna/__init__.py +16 -0
- agent_dna-0.1.0/agentdna/core.py +120 -0
- agent_dna-0.1.0/agentdna/handler.py +478 -0
- agent_dna-0.1.0/agentdna/node_client.py +67 -0
- agent_dna-0.1.0/agentdna/token.txt +0 -0
- agent_dna-0.1.0/agentdna/trust.py +217 -0
- agent_dna-0.1.0/pyproject.toml +28 -0
- agent_dna-0.1.0/setup.cfg +4 -0
agent_dna-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
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.
|
agent_dna-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-dna
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AgentDNA: Verifiable and Auditable AI Agents
|
|
5
|
+
Author: Aparna Ullas
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rubixchain/agentdna
|
|
8
|
+
Project-URL: Repository, https://github.com/rubixchain/agentdna
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: requests>=2.0.0
|
|
13
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
+
Requires-Dist: rubix-py
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# AgentDNA
|
|
19
|
+
|
|
20
|
+
AgentDNA is a package that helps in auditing and verifiability of Agents within a multi-agent communication system.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Key Features
|
|
24
|
+
- **Unified trust layer** for multi-agent systems
|
|
25
|
+
- Automatically manages:
|
|
26
|
+
- DID setup
|
|
27
|
+
- Signing traces of conversation
|
|
28
|
+
- Verification of Agent conversation
|
|
29
|
+
- Immutable audit logging
|
|
30
|
+
- Fully compatible with:
|
|
31
|
+
- Google A2A protocol
|
|
32
|
+
- ADK, Crew and LangGraph frameworks
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
```
|
|
36
|
+
# Installation via pip
|
|
37
|
+
pip install agent-dna
|
|
38
|
+
|
|
39
|
+
# Installation via uv
|
|
40
|
+
uv add agent-dna
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
AgentDNA internally wraps several layers to keep agent developers free from Rubix-specific complexity.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
┌─────────────────────────┐
|
|
48
|
+
│ Agent Developer │
|
|
49
|
+
│ dna.build() / handle() │
|
|
50
|
+
└─────────────┬───────────┘
|
|
51
|
+
│
|
|
52
|
+
┌─────────────────────────┐
|
|
53
|
+
│ AgentDNA │
|
|
54
|
+
│ role = "host" | "remote"│
|
|
55
|
+
└─────────────┬───────────┘
|
|
56
|
+
│
|
|
57
|
+
┌─────────────────────────┐
|
|
58
|
+
│ RubixMessageHandler |
|
|
59
|
+
│ - build host/agent msgs │
|
|
60
|
+
│ - parse & verify inbound│
|
|
61
|
+
│ - NFT execution (host) │
|
|
62
|
+
└─────────────┬───────────┘
|
|
63
|
+
│
|
|
64
|
+
┌───────────────────────────┐
|
|
65
|
+
│ RubixTrustService │
|
|
66
|
+
│ - DID management │
|
|
67
|
+
│ - sign_envelope() │
|
|
68
|
+
│ - verify_envelope() │
|
|
69
|
+
│ - verify_message_payload()│
|
|
70
|
+
└─────────────┬─────────────┘
|
|
71
|
+
│
|
|
72
|
+
┌─────────────────────────┐
|
|
73
|
+
│ rubix-py SDK │
|
|
74
|
+
│ RubixClient │
|
|
75
|
+
│ Signer │
|
|
76
|
+
│ Querier │
|
|
77
|
+
└─────────────────────────┘
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Agent Roles
|
|
81
|
+
AgentDNA supports two roles:
|
|
82
|
+
|
|
83
|
+
### **Host Agent**
|
|
84
|
+
Responsible for:
|
|
85
|
+
- Signing and sending outgoing **host_request**
|
|
86
|
+
- Verifying inbound **agent_response**
|
|
87
|
+
- Optional **NFT execution** for audit logging
|
|
88
|
+
|
|
89
|
+
### **Remote Agent**
|
|
90
|
+
Responsible for:
|
|
91
|
+
- Verifying inbound **host_request**
|
|
92
|
+
- Signing outbound **agent_response**
|
|
93
|
+
|
|
94
|
+
## Quick Start Example
|
|
95
|
+
### **Initializing**
|
|
96
|
+
```python
|
|
97
|
+
from agentdna import AgentDNA
|
|
98
|
+
|
|
99
|
+
dna = AgentDNA(alias="<agent alias>", role="<host/remote>")
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
### **Remote Agents**
|
|
103
|
+
```python
|
|
104
|
+
verify_info = await dna.handle(raw_text=raw_message, verify_mode="<light/heavy>")
|
|
105
|
+
|
|
106
|
+
reply = run_llm(original_msg)
|
|
107
|
+
|
|
108
|
+
built = dna.build(
|
|
109
|
+
original_message=original_msg,
|
|
110
|
+
response=reply,
|
|
111
|
+
host_block=host_block,
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### **Host Agent**
|
|
116
|
+
```python
|
|
117
|
+
outbound = dna.build(
|
|
118
|
+
original_message="Are you free tomorrow?",
|
|
119
|
+
state={"task_id": tid, "context_id": cid}
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
result = await self.dna.handle(
|
|
123
|
+
resp_parts=resp_parts,
|
|
124
|
+
original_task=task,
|
|
125
|
+
remote_name=agent_name,
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Project Structure
|
|
130
|
+
```
|
|
131
|
+
agentdna/
|
|
132
|
+
├── core.py
|
|
133
|
+
├── handler.py
|
|
134
|
+
├── trust.py
|
|
135
|
+
├── node_client.py
|
|
136
|
+
└── ...
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Examples
|
|
140
|
+
Full Host, ADK, and LangGraph examples can be found inside `examples/`.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
MIT
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
|
|
2
|
+
# AgentDNA
|
|
3
|
+
|
|
4
|
+
AgentDNA is a package that helps in auditing and verifiability of Agents within a multi-agent communication system.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
- **Unified trust layer** for multi-agent systems
|
|
9
|
+
- Automatically manages:
|
|
10
|
+
- DID setup
|
|
11
|
+
- Signing traces of conversation
|
|
12
|
+
- Verification of Agent conversation
|
|
13
|
+
- Immutable audit logging
|
|
14
|
+
- Fully compatible with:
|
|
15
|
+
- Google A2A protocol
|
|
16
|
+
- ADK, Crew and LangGraph frameworks
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
```
|
|
20
|
+
# Installation via pip
|
|
21
|
+
pip install agent-dna
|
|
22
|
+
|
|
23
|
+
# Installation via uv
|
|
24
|
+
uv add agent-dna
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
AgentDNA internally wraps several layers to keep agent developers free from Rubix-specific complexity.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────────────────┐
|
|
32
|
+
│ Agent Developer │
|
|
33
|
+
│ dna.build() / handle() │
|
|
34
|
+
└─────────────┬───────────┘
|
|
35
|
+
│
|
|
36
|
+
┌─────────────────────────┐
|
|
37
|
+
│ AgentDNA │
|
|
38
|
+
│ role = "host" | "remote"│
|
|
39
|
+
└─────────────┬───────────┘
|
|
40
|
+
│
|
|
41
|
+
┌─────────────────────────┐
|
|
42
|
+
│ RubixMessageHandler |
|
|
43
|
+
│ - build host/agent msgs │
|
|
44
|
+
│ - parse & verify inbound│
|
|
45
|
+
│ - NFT execution (host) │
|
|
46
|
+
└─────────────┬───────────┘
|
|
47
|
+
│
|
|
48
|
+
┌───────────────────────────┐
|
|
49
|
+
│ RubixTrustService │
|
|
50
|
+
│ - DID management │
|
|
51
|
+
│ - sign_envelope() │
|
|
52
|
+
│ - verify_envelope() │
|
|
53
|
+
│ - verify_message_payload()│
|
|
54
|
+
└─────────────┬─────────────┘
|
|
55
|
+
│
|
|
56
|
+
┌─────────────────────────┐
|
|
57
|
+
│ rubix-py SDK │
|
|
58
|
+
│ RubixClient │
|
|
59
|
+
│ Signer │
|
|
60
|
+
│ Querier │
|
|
61
|
+
└─────────────────────────┘
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Agent Roles
|
|
65
|
+
AgentDNA supports two roles:
|
|
66
|
+
|
|
67
|
+
### **Host Agent**
|
|
68
|
+
Responsible for:
|
|
69
|
+
- Signing and sending outgoing **host_request**
|
|
70
|
+
- Verifying inbound **agent_response**
|
|
71
|
+
- Optional **NFT execution** for audit logging
|
|
72
|
+
|
|
73
|
+
### **Remote Agent**
|
|
74
|
+
Responsible for:
|
|
75
|
+
- Verifying inbound **host_request**
|
|
76
|
+
- Signing outbound **agent_response**
|
|
77
|
+
|
|
78
|
+
## Quick Start Example
|
|
79
|
+
### **Initializing**
|
|
80
|
+
```python
|
|
81
|
+
from agentdna import AgentDNA
|
|
82
|
+
|
|
83
|
+
dna = AgentDNA(alias="<agent alias>", role="<host/remote>")
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
### **Remote Agents**
|
|
87
|
+
```python
|
|
88
|
+
verify_info = await dna.handle(raw_text=raw_message, verify_mode="<light/heavy>")
|
|
89
|
+
|
|
90
|
+
reply = run_llm(original_msg)
|
|
91
|
+
|
|
92
|
+
built = dna.build(
|
|
93
|
+
original_message=original_msg,
|
|
94
|
+
response=reply,
|
|
95
|
+
host_block=host_block,
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### **Host Agent**
|
|
100
|
+
```python
|
|
101
|
+
outbound = dna.build(
|
|
102
|
+
original_message="Are you free tomorrow?",
|
|
103
|
+
state={"task_id": tid, "context_id": cid}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
result = await self.dna.handle(
|
|
107
|
+
resp_parts=resp_parts,
|
|
108
|
+
original_task=task,
|
|
109
|
+
remote_name=agent_name,
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Project Structure
|
|
114
|
+
```
|
|
115
|
+
agentdna/
|
|
116
|
+
├── core.py
|
|
117
|
+
├── handler.py
|
|
118
|
+
├── trust.py
|
|
119
|
+
├── node_client.py
|
|
120
|
+
└── ...
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Examples
|
|
124
|
+
Full Host, ADK, and LangGraph examples can be found inside `examples/`.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
MIT
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-dna
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AgentDNA: Verifiable and Auditable AI Agents
|
|
5
|
+
Author: Aparna Ullas
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rubixchain/agentdna
|
|
8
|
+
Project-URL: Repository, https://github.com/rubixchain/agentdna
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: requests>=2.0.0
|
|
13
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
+
Requires-Dist: rubix-py
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# AgentDNA
|
|
19
|
+
|
|
20
|
+
AgentDNA is a package that helps in auditing and verifiability of Agents within a multi-agent communication system.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Key Features
|
|
24
|
+
- **Unified trust layer** for multi-agent systems
|
|
25
|
+
- Automatically manages:
|
|
26
|
+
- DID setup
|
|
27
|
+
- Signing traces of conversation
|
|
28
|
+
- Verification of Agent conversation
|
|
29
|
+
- Immutable audit logging
|
|
30
|
+
- Fully compatible with:
|
|
31
|
+
- Google A2A protocol
|
|
32
|
+
- ADK, Crew and LangGraph frameworks
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
```
|
|
36
|
+
# Installation via pip
|
|
37
|
+
pip install agent-dna
|
|
38
|
+
|
|
39
|
+
# Installation via uv
|
|
40
|
+
uv add agent-dna
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
AgentDNA internally wraps several layers to keep agent developers free from Rubix-specific complexity.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
┌─────────────────────────┐
|
|
48
|
+
│ Agent Developer │
|
|
49
|
+
│ dna.build() / handle() │
|
|
50
|
+
└─────────────┬───────────┘
|
|
51
|
+
│
|
|
52
|
+
┌─────────────────────────┐
|
|
53
|
+
│ AgentDNA │
|
|
54
|
+
│ role = "host" | "remote"│
|
|
55
|
+
└─────────────┬───────────┘
|
|
56
|
+
│
|
|
57
|
+
┌─────────────────────────┐
|
|
58
|
+
│ RubixMessageHandler |
|
|
59
|
+
│ - build host/agent msgs │
|
|
60
|
+
│ - parse & verify inbound│
|
|
61
|
+
│ - NFT execution (host) │
|
|
62
|
+
└─────────────┬───────────┘
|
|
63
|
+
│
|
|
64
|
+
┌───────────────────────────┐
|
|
65
|
+
│ RubixTrustService │
|
|
66
|
+
│ - DID management │
|
|
67
|
+
│ - sign_envelope() │
|
|
68
|
+
│ - verify_envelope() │
|
|
69
|
+
│ - verify_message_payload()│
|
|
70
|
+
└─────────────┬─────────────┘
|
|
71
|
+
│
|
|
72
|
+
┌─────────────────────────┐
|
|
73
|
+
│ rubix-py SDK │
|
|
74
|
+
│ RubixClient │
|
|
75
|
+
│ Signer │
|
|
76
|
+
│ Querier │
|
|
77
|
+
└─────────────────────────┘
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Agent Roles
|
|
81
|
+
AgentDNA supports two roles:
|
|
82
|
+
|
|
83
|
+
### **Host Agent**
|
|
84
|
+
Responsible for:
|
|
85
|
+
- Signing and sending outgoing **host_request**
|
|
86
|
+
- Verifying inbound **agent_response**
|
|
87
|
+
- Optional **NFT execution** for audit logging
|
|
88
|
+
|
|
89
|
+
### **Remote Agent**
|
|
90
|
+
Responsible for:
|
|
91
|
+
- Verifying inbound **host_request**
|
|
92
|
+
- Signing outbound **agent_response**
|
|
93
|
+
|
|
94
|
+
## Quick Start Example
|
|
95
|
+
### **Initializing**
|
|
96
|
+
```python
|
|
97
|
+
from agentdna import AgentDNA
|
|
98
|
+
|
|
99
|
+
dna = AgentDNA(alias="<agent alias>", role="<host/remote>")
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
### **Remote Agents**
|
|
103
|
+
```python
|
|
104
|
+
verify_info = await dna.handle(raw_text=raw_message, verify_mode="<light/heavy>")
|
|
105
|
+
|
|
106
|
+
reply = run_llm(original_msg)
|
|
107
|
+
|
|
108
|
+
built = dna.build(
|
|
109
|
+
original_message=original_msg,
|
|
110
|
+
response=reply,
|
|
111
|
+
host_block=host_block,
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### **Host Agent**
|
|
116
|
+
```python
|
|
117
|
+
outbound = dna.build(
|
|
118
|
+
original_message="Are you free tomorrow?",
|
|
119
|
+
state={"task_id": tid, "context_id": cid}
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
result = await self.dna.handle(
|
|
123
|
+
resp_parts=resp_parts,
|
|
124
|
+
original_task=task,
|
|
125
|
+
remote_name=agent_name,
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Project Structure
|
|
130
|
+
```
|
|
131
|
+
agentdna/
|
|
132
|
+
├── core.py
|
|
133
|
+
├── handler.py
|
|
134
|
+
├── trust.py
|
|
135
|
+
├── node_client.py
|
|
136
|
+
└── ...
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Examples
|
|
140
|
+
Full Host, ADK, and LangGraph examples can be found inside `examples/`.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
agent_dna.egg-info/PKG-INFO
|
|
5
|
+
agent_dna.egg-info/SOURCES.txt
|
|
6
|
+
agent_dna.egg-info/dependency_links.txt
|
|
7
|
+
agent_dna.egg-info/requires.txt
|
|
8
|
+
agent_dna.egg-info/top_level.txt
|
|
9
|
+
agentdna/__init__.py
|
|
10
|
+
agentdna/core.py
|
|
11
|
+
agentdna/handler.py
|
|
12
|
+
agentdna/node_client.py
|
|
13
|
+
agentdna/token.txt
|
|
14
|
+
agentdna/trust.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
agentdna
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
rubix.agent.dna
|
|
3
|
+
Public interface for Rubix agent DNA utilities.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .trust import RubixTrustService
|
|
7
|
+
from .handler import RubixMessageHandler
|
|
8
|
+
from .node_client import NodeClient
|
|
9
|
+
from .core import AgentDNA
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"RubixTrustService",
|
|
13
|
+
"RubixMessageHandler",
|
|
14
|
+
"NodeClient",
|
|
15
|
+
"AgentDNA"
|
|
16
|
+
]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from .trust import RubixTrustService
|
|
5
|
+
from .handler import RubixMessageHandler
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentDNA:
|
|
9
|
+
"""
|
|
10
|
+
Single entry point for agent developers.
|
|
11
|
+
|
|
12
|
+
They only call:
|
|
13
|
+
dna.build(...) # outbound message (request or response)
|
|
14
|
+
await dna.handle(...) # inbound message (request or response)
|
|
15
|
+
|
|
16
|
+
Behavior is decided purely by `role`:
|
|
17
|
+
|
|
18
|
+
role="host":
|
|
19
|
+
- build -> host_request (host → remote)
|
|
20
|
+
- handle -> host (remote → host, verify + NFT)
|
|
21
|
+
|
|
22
|
+
role="remote":
|
|
23
|
+
- build -> agent_response (remote → host)
|
|
24
|
+
- handle -> remote (host → remote, verify host)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
alias: str,
|
|
30
|
+
role: str = "remote", # "host" or "remote"
|
|
31
|
+
token_filename: str = "token.txt",
|
|
32
|
+
) -> None:
|
|
33
|
+
if role not in ("host", "remote"):
|
|
34
|
+
raise ValueError("AgentDNA.role must be 'host' or 'remote'")
|
|
35
|
+
|
|
36
|
+
self.role = role
|
|
37
|
+
self.trust = RubixTrustService(alias=alias)
|
|
38
|
+
|
|
39
|
+
self.handler = RubixMessageHandler(
|
|
40
|
+
alias=alias,
|
|
41
|
+
token_filename=token_filename,
|
|
42
|
+
trust_service=self.trust,
|
|
43
|
+
enable_nft=(role == "host"),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# ------------------------------------------------------------------
|
|
47
|
+
# BUILD: outbound messages
|
|
48
|
+
# ------------------------------------------------------------------
|
|
49
|
+
def build(self, **kwargs) -> Dict[str, Any]:
|
|
50
|
+
"""
|
|
51
|
+
Host:
|
|
52
|
+
dna.build(
|
|
53
|
+
original_message=task,
|
|
54
|
+
state=tool_context.state or {},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
Remote:
|
|
58
|
+
dna.build(
|
|
59
|
+
original_message=original_message,
|
|
60
|
+
response=agent_reply_text,
|
|
61
|
+
host_block=host_block,
|
|
62
|
+
extra={...},
|
|
63
|
+
)
|
|
64
|
+
"""
|
|
65
|
+
if self.role == "host":
|
|
66
|
+
if "original_message" not in kwargs:
|
|
67
|
+
raise ValueError("Host.build() requires original_message")
|
|
68
|
+
return self.handler.build(
|
|
69
|
+
kind="host_request",
|
|
70
|
+
**kwargs,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# remote
|
|
74
|
+
if "original_message" not in kwargs or "response" not in kwargs:
|
|
75
|
+
raise ValueError("Remote.build() requires original_message and response")
|
|
76
|
+
return self.handler.build(
|
|
77
|
+
kind="agent_response",
|
|
78
|
+
**kwargs,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# ------------------------------------------------------------------
|
|
82
|
+
# HANDLE: inbound messages
|
|
83
|
+
# ------------------------------------------------------------------
|
|
84
|
+
async def handle(self, **kwargs) -> Dict[str, Any]:
|
|
85
|
+
"""
|
|
86
|
+
Host:
|
|
87
|
+
result = await dna.handle(
|
|
88
|
+
resp_parts=resp_parts,
|
|
89
|
+
original_task=task,
|
|
90
|
+
remote_name=agent_name,
|
|
91
|
+
execute_nft=True,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
Remote:
|
|
95
|
+
verify_info = await dna.handle(
|
|
96
|
+
raw_text=raw,
|
|
97
|
+
verify_mode="light",
|
|
98
|
+
)
|
|
99
|
+
"""
|
|
100
|
+
if self.role == "remote":
|
|
101
|
+
# Remote handling inbound from host
|
|
102
|
+
raw_text = kwargs.get("raw_text")
|
|
103
|
+
if raw_text is None:
|
|
104
|
+
raise ValueError("Remote.handle() requires raw_text")
|
|
105
|
+
|
|
106
|
+
mode = kwargs.get("verify_mode", "light")
|
|
107
|
+
# trust.verify_message_payload is sync, but it's fine to call
|
|
108
|
+
return self.trust.verify_message_payload(
|
|
109
|
+
raw_text=raw_text,
|
|
110
|
+
mode=mode,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Host handling inbound from remotes
|
|
114
|
+
for required in ("resp_parts", "original_task", "remote_name"):
|
|
115
|
+
if required not in kwargs:
|
|
116
|
+
raise ValueError(f"Host.handle() requires {required}")
|
|
117
|
+
return await self.handler.handle(
|
|
118
|
+
kind="host",
|
|
119
|
+
**kwargs,
|
|
120
|
+
)
|