agentwit 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.
- agentwit-0.1.0/.claude/settings.local.json +14 -0
- agentwit-0.1.0/.gitignore +73 -0
- agentwit-0.1.0/LICENSE +21 -0
- agentwit-0.1.0/PKG-INFO +227 -0
- agentwit-0.1.0/README.ja.md +193 -0
- agentwit-0.1.0/README.md +193 -0
- agentwit-0.1.0/agentwit/__init__.py +5 -0
- agentwit-0.1.0/agentwit/analyzer/__init__.py +5 -0
- agentwit-0.1.0/agentwit/analyzer/scorer.py +77 -0
- agentwit-0.1.0/agentwit/analyzer/timeline.py +45 -0
- agentwit-0.1.0/agentwit/cli.py +288 -0
- agentwit-0.1.0/agentwit/ingest/__init__.py +4 -0
- agentwit-0.1.0/agentwit/ingest/server.py +37 -0
- agentwit-0.1.0/agentwit/proxy/__init__.py +4 -0
- agentwit-0.1.0/agentwit/proxy/http_proxy.py +184 -0
- agentwit-0.1.0/agentwit/proxy/sse_proxy.py +37 -0
- agentwit-0.1.0/agentwit/proxy/stdio_proxy.py +37 -0
- agentwit-0.1.0/agentwit/reporter/__init__.py +6 -0
- agentwit-0.1.0/agentwit/reporter/html_reporter.py +51 -0
- agentwit-0.1.0/agentwit/reporter/json_reporter.py +115 -0
- agentwit-0.1.0/agentwit/reporter/markdown_reporter.py +51 -0
- agentwit-0.1.0/agentwit/witness/__init__.py +5 -0
- agentwit-0.1.0/agentwit/witness/chain.py +156 -0
- agentwit-0.1.0/agentwit/witness/log.py +143 -0
- agentwit-0.1.0/examples/demo.sh +236 -0
- agentwit-0.1.0/examples/dummy_mcp_server.py +138 -0
- agentwit-0.1.0/examples/quickstart_http.py +112 -0
- agentwit-0.1.0/examples/sample_witness_log.json +111 -0
- agentwit-0.1.0/pyproject.toml +51 -0
- agentwit-0.1.0/tests/__init__.py +1 -0
- agentwit-0.1.0/tests/test_chain.py +154 -0
- agentwit-0.1.0/tests/test_scorer.py +149 -0
- agentwit-0.1.0/tests/test_witness_log.py +159 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
downloads/
|
|
10
|
+
eggs/
|
|
11
|
+
.eggs/
|
|
12
|
+
lib/
|
|
13
|
+
lib64/
|
|
14
|
+
parts/
|
|
15
|
+
sdist/
|
|
16
|
+
var/
|
|
17
|
+
wheels/
|
|
18
|
+
share/python-wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
dist/
|
|
24
|
+
|
|
25
|
+
# Virtual environments
|
|
26
|
+
.env
|
|
27
|
+
.venv
|
|
28
|
+
env/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
env.bak/
|
|
32
|
+
venv.bak/
|
|
33
|
+
|
|
34
|
+
# Testing
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
.coverage
|
|
38
|
+
.coverage.*
|
|
39
|
+
.cache
|
|
40
|
+
nosetests.xml
|
|
41
|
+
coverage.xml
|
|
42
|
+
*.cover
|
|
43
|
+
*.py,cover
|
|
44
|
+
.hypothesis/
|
|
45
|
+
.pytest_cache/
|
|
46
|
+
htmlcov/
|
|
47
|
+
|
|
48
|
+
# Type checking
|
|
49
|
+
.mypy_cache/
|
|
50
|
+
.dmypy.json
|
|
51
|
+
dmypy.json
|
|
52
|
+
.pytype/
|
|
53
|
+
.pyre/
|
|
54
|
+
|
|
55
|
+
# IDE
|
|
56
|
+
.idea/
|
|
57
|
+
.vscode/
|
|
58
|
+
*.swp
|
|
59
|
+
*.swo
|
|
60
|
+
*~
|
|
61
|
+
.DS_Store
|
|
62
|
+
|
|
63
|
+
# agentwit — witness log output
|
|
64
|
+
witness_logs/
|
|
65
|
+
*.jsonl
|
|
66
|
+
/tmp/agentwit_*/
|
|
67
|
+
|
|
68
|
+
# Secrets
|
|
69
|
+
.env
|
|
70
|
+
.env.*
|
|
71
|
+
*.pem
|
|
72
|
+
*.key
|
|
73
|
+
secrets.json
|
agentwit-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 agentwit contributors
|
|
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.
|
agentwit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentwit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Transparent proxy witness for AI agent ↔ MCP server communications
|
|
5
|
+
Project-URL: Homepage, https://github.com/tokotokokame/agentwit
|
|
6
|
+
Project-URL: Repository, https://github.com/tokotokokame/agentwit
|
|
7
|
+
Project-URL: Issues, https://github.com/tokotokokame/agentwit/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/tokotokokame/agentwit/releases
|
|
9
|
+
Author: tokotokokame
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai-agent,audit,llm,mcp,proxy,security,witness
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: System :: Logging
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: anyio>=4.3.0
|
|
25
|
+
Requires-Dist: click>=8.1.0
|
|
26
|
+
Requires-Dist: fastapi>=0.111.0
|
|
27
|
+
Requires-Dist: httpx>=0.27.0
|
|
28
|
+
Requires-Dist: uvicorn[standard]>=0.29.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# agentwit
|
|
36
|
+
|
|
37
|
+
> Transparent witness for AI agent ↔ MCP server communications
|
|
38
|
+
|
|
39
|
+
[日本語版 / Japanese](README.ja.md)
|
|
40
|
+
|
|
41
|
+
[](https://www.python.org/)
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
[](#)
|
|
44
|
+
|
|
45
|
+
## What is agentwit?
|
|
46
|
+
|
|
47
|
+
agentwit is a transparent proxy that sits between AI agents and MCP servers,
|
|
48
|
+
recording every communication as a tamper-proof witness log.
|
|
49
|
+
|
|
50
|
+
Unlike existing tools that act as **"guards"** (blocking suspicious traffic),
|
|
51
|
+
agentwit acts as a **"witness"** — it never blocks, never interferes, but
|
|
52
|
+
records everything with cryptographic chain integrity.
|
|
53
|
+
|
|
54
|
+
## Guard vs. Witness
|
|
55
|
+
|
|
56
|
+
| Tool | Approach | Blocks traffic | Tamper-proof log |
|
|
57
|
+
|--------------|-------------------|:--------------:|:----------------:|
|
|
58
|
+
| mcp-scan | Proxy + Guard | ✅ | ❌ |
|
|
59
|
+
| Proximity | Static scanner | — | ❌ |
|
|
60
|
+
| Intercept | Policy proxy | ✅ | ❌ |
|
|
61
|
+
| **agentwit** | **Witness proxy** | **❌** | **✅** |
|
|
62
|
+
|
|
63
|
+
## How it works
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
AI Agent
|
|
67
|
+
│
|
|
68
|
+
▼
|
|
69
|
+
agentwit proxy ◄── records every message with chain hash
|
|
70
|
+
│ never blocks, fully transparent
|
|
71
|
+
▼
|
|
72
|
+
MCP Server ◄── zero modification required
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Each recorded event is chained to the previous one via SHA-256:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
genesis_hash = sha256("genesis:" + session_id)
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
event_1: session_chain = sha256(genesis_hash + hash(event_1))
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
event_2: session_chain = sha256(event_1_chain + hash(event_2))
|
|
85
|
+
│
|
|
86
|
+
▼
|
|
87
|
+
...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Any single-byte modification to any event breaks the entire chain from
|
|
91
|
+
that point forward — making tampering immediately detectable.
|
|
92
|
+
|
|
93
|
+
## Quick Start
|
|
94
|
+
|
|
95
|
+
### Installation
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install agentwit
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 1. Start the witness proxy
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
agentwit proxy --target http://localhost:3000 --port 8765
|
|
105
|
+
# Starting agentwit proxy → http://localhost:3000
|
|
106
|
+
# Listening on 127.0.0.1:8765
|
|
107
|
+
# Session: ./witness_logs/session_20260314_120000
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2. Point your agent to the proxy
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Before: http://localhost:3000
|
|
114
|
+
# After: http://localhost:8765
|
|
115
|
+
# That's it. No other changes needed.
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Generate an audit report
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
agentwit report --session ./witness_logs/session_20260314_120000 \
|
|
122
|
+
--format html --output report.html
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. Verify chain integrity
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
agentwit replay --session ./witness_logs/session_20260314_120000
|
|
129
|
+
# Session: session_20260314_120000 (6 events)
|
|
130
|
+
# Chain integrity: VALID
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Commands
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
agentwit proxy --target URL [--port 8765] [--log-dir ./witness_logs] [--actor NAME]
|
|
137
|
+
agentwit report --session DIR [--format json|markdown|html] [--output FILE]
|
|
138
|
+
agentwit replay --session DIR [--verify/--no-verify]
|
|
139
|
+
agentwit diff --session-a DIR --session-b DIR
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
| Command | Description |
|
|
143
|
+
|-----------|------------------------------------------------|
|
|
144
|
+
| `proxy` | Start the transparent witness proxy |
|
|
145
|
+
| `report` | Generate audit report (json / markdown / html) |
|
|
146
|
+
| `replay` | Replay and verify chain integrity of a session |
|
|
147
|
+
| `diff` | Compare two sessions side by side |
|
|
148
|
+
|
|
149
|
+
## Witness Log Format
|
|
150
|
+
|
|
151
|
+
Each intercepted event is stored as one JSON line in `witness.jsonl`:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"witness_id": "sha256 of the entire signed event",
|
|
156
|
+
"session_chain": "sha256(prev_chain_hash + event_hash)",
|
|
157
|
+
"timestamp": "2026-03-14T12:18:53.708937+00:00",
|
|
158
|
+
"actor": "demo-agent",
|
|
159
|
+
"action": "tools/call",
|
|
160
|
+
"tool": "bash",
|
|
161
|
+
"input_hash": "sha256 of the input payload",
|
|
162
|
+
"output_hash": "sha256 of the output payload",
|
|
163
|
+
"full_payload": { "params": {}, "result": {} },
|
|
164
|
+
"risk_indicators": [
|
|
165
|
+
{ "pattern": "shell_exec", "severity": "high", "matched": "bash" }
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Events are appended to a JSONL file as they arrive — the proxy never
|
|
171
|
+
buffers or delays the upstream response.
|
|
172
|
+
|
|
173
|
+
## Tamper Detection
|
|
174
|
+
|
|
175
|
+
Modify any field in the log and agentwit detects it immediately:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Simulate tampering: change "actor" in event[0]
|
|
179
|
+
python3 -c "
|
|
180
|
+
import json; lines=open('witness.jsonl').readlines()
|
|
181
|
+
e=json.loads(lines[0]); e['actor']='ATTACKER'
|
|
182
|
+
lines[0]=json.dumps(e)+'\n'; open('witness.jsonl','w').writelines(lines)
|
|
183
|
+
"
|
|
184
|
+
|
|
185
|
+
agentwit replay --session ./witness_logs/session_20260314_120000
|
|
186
|
+
# Session: session_20260314_120000 (6 events)
|
|
187
|
+
# Chain integrity: TAMPERED
|
|
188
|
+
# [event 0] FAIL - session_chain mismatch:
|
|
189
|
+
# expected '0fd4d24bcb3dab7d171e…'
|
|
190
|
+
# got 'a79a9e4cdb19795a521e…'
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Use Cases
|
|
194
|
+
|
|
195
|
+
- **Security engineers** auditing AI agent behavior in production
|
|
196
|
+
- **Enterprise teams** requiring AI activity compliance logs
|
|
197
|
+
- **AI researchers** reproducibly comparing agent sessions
|
|
198
|
+
- **Penetration testers** documenting MCP tool usage as evidence
|
|
199
|
+
|
|
200
|
+
## Python API
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from agentwit import WitnessLogger, ChainManager
|
|
204
|
+
|
|
205
|
+
# Direct logging (no proxy needed)
|
|
206
|
+
logger = WitnessLogger(session_dir="./logs", actor="my-agent")
|
|
207
|
+
event = logger.log_event(
|
|
208
|
+
action="tools/call",
|
|
209
|
+
tool="bash",
|
|
210
|
+
full_payload={"params": {"command": "ls"}, "result": {"stdout": "..."}}
|
|
211
|
+
)
|
|
212
|
+
logger.close()
|
|
213
|
+
|
|
214
|
+
# Verify a recorded session
|
|
215
|
+
chain = ChainManager(session_id="session_20260314_120000")
|
|
216
|
+
results = chain.verify_chain(events)
|
|
217
|
+
all_valid = all(r["valid"] for r in results)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Requirements
|
|
221
|
+
|
|
222
|
+
- Python 3.10+
|
|
223
|
+
- FastAPI, uvicorn, httpx, click (installed automatically)
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
[MIT](LICENSE) © agentwit contributors
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# agentwit
|
|
2
|
+
|
|
3
|
+
> AIエージェントとMCPサーバー間の通信を記録する透過型Witnessプロキシ
|
|
4
|
+
|
|
5
|
+
[English](README.md)
|
|
6
|
+
|
|
7
|
+
[](https://www.python.org/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](#)
|
|
10
|
+
|
|
11
|
+
## agentwit とは?
|
|
12
|
+
|
|
13
|
+
agentwit は、AIエージェントとMCPサーバーの間に置く透過型プロキシです。
|
|
14
|
+
すべての通信を改ざん検知可能なWitness Log(改ざん検知ログ)として記録します。
|
|
15
|
+
|
|
16
|
+
不審なトラフィックをブロックする **「ガード」** 型の既存ツールとは異なり、
|
|
17
|
+
agentwit は **「証人(Witness)」** として動作します。
|
|
18
|
+
通信をブロックせず、改変もせず、ただ暗号化されたChain Integrity(チェーン整合性)付きですべてを記録します。
|
|
19
|
+
|
|
20
|
+
## Guard(ガード)vs. Witness(証人)
|
|
21
|
+
|
|
22
|
+
| ツール | アプローチ | 通信のブロック | 改ざん検知ログ |
|
|
23
|
+
|--------------|-------------------|:--------------:|:--------------:|
|
|
24
|
+
| mcp-scan | プロキシ + ガード | ✅ | ❌ |
|
|
25
|
+
| Proximity | 静的スキャナー | — | ❌ |
|
|
26
|
+
| Intercept | ポリシープロキシ | ✅ | ❌ |
|
|
27
|
+
| **agentwit** | **Witnessプロキシ** | **❌** | **✅** |
|
|
28
|
+
|
|
29
|
+
## 仕組み
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
AIエージェント
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
agentwit proxy ◄── 全メッセージをChainハッシュ付きで記録
|
|
36
|
+
│ ブロックなし・完全透過
|
|
37
|
+
▼
|
|
38
|
+
MCPサーバー ◄── 変更不要・そのまま動作
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
記録された各イベントは SHA-256 でチェーン状に連結されます:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
genesis_hash = sha256("genesis:" + session_id)
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
event_1: session_chain = sha256(genesis_hash + hash(event_1))
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
event_2: session_chain = sha256(event_1_chain + hash(event_2))
|
|
51
|
+
│
|
|
52
|
+
▼
|
|
53
|
+
...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
どのイベントに対しても1バイトの変更を加えると、その時点からチェーン全体が壊れます。
|
|
57
|
+
これにより改ざんを即座に検出できます。
|
|
58
|
+
|
|
59
|
+
## クイックスタート
|
|
60
|
+
|
|
61
|
+
### インストール
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install agentwit
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 1. Witnessプロキシを起動
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
agentwit proxy --target http://localhost:3000 --port 8765
|
|
71
|
+
# Starting agentwit proxy → http://localhost:3000
|
|
72
|
+
# Listening on 127.0.0.1:8765
|
|
73
|
+
# Session: ./witness_logs/session_20260314_120000
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. エージェントの向き先をプロキシに変更
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# 変更前: http://localhost:3000
|
|
80
|
+
# 変更後: http://localhost:8765
|
|
81
|
+
# 以上です。他に変更は不要です。
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. 監査レポートを生成
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
agentwit report --session ./witness_logs/session_20260314_120000 \
|
|
88
|
+
--format html --output report.html
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 4. Chain Integrityを検証
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
agentwit replay --session ./witness_logs/session_20260314_120000
|
|
95
|
+
# Session: session_20260314_120000 (6 events)
|
|
96
|
+
# Chain integrity: VALID
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## コマンド一覧
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
agentwit proxy --target URL [--port 8765] [--log-dir ./witness_logs] [--actor NAME]
|
|
103
|
+
agentwit report --session DIR [--format json|markdown|html] [--output FILE]
|
|
104
|
+
agentwit replay --session DIR [--verify/--no-verify]
|
|
105
|
+
agentwit diff --session-a DIR --session-b DIR
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
| コマンド | 説明 |
|
|
109
|
+
|-----------|----------------------------------------------------------|
|
|
110
|
+
| `proxy` | 透過Witnessプロキシを起動 |
|
|
111
|
+
| `report` | 監査レポートを生成(json / markdown / html) |
|
|
112
|
+
| `replay` | セッションを再生しChain Integrityを検証 |
|
|
113
|
+
| `diff` | 2つのセッションを並べて比較 |
|
|
114
|
+
|
|
115
|
+
## Witness Logのフォーマット
|
|
116
|
+
|
|
117
|
+
傍受された各イベントは `witness.jsonl` に1行のJSONとして記録されます:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"witness_id": "イベント全体のsha256",
|
|
122
|
+
"session_chain": "sha256(直前のchain_hash + event_hash)",
|
|
123
|
+
"timestamp": "2026-03-14T12:18:53.708937+00:00",
|
|
124
|
+
"actor": "demo-agent",
|
|
125
|
+
"action": "tools/call",
|
|
126
|
+
"tool": "bash",
|
|
127
|
+
"input_hash": "入力ペイロードのsha256",
|
|
128
|
+
"output_hash": "出力ペイロードのsha256",
|
|
129
|
+
"full_payload": { "params": {}, "result": {} },
|
|
130
|
+
"risk_indicators": [
|
|
131
|
+
{ "pattern": "shell_exec", "severity": "high", "matched": "bash" }
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
イベントは到着と同時にJSONLファイルへ追記されます。
|
|
137
|
+
プロキシは上流のレスポンスをバッファリングせず、遅延も発生しません。
|
|
138
|
+
|
|
139
|
+
## 改ざん検知
|
|
140
|
+
|
|
141
|
+
ログのどのフィールドを変更しても、agentwit は即座に検出します:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# 改ざんのシミュレーション: event[0] の "actor" フィールドを変更
|
|
145
|
+
python3 -c "
|
|
146
|
+
import json; lines=open('witness.jsonl').readlines()
|
|
147
|
+
e=json.loads(lines[0]); e['actor']='ATTACKER'
|
|
148
|
+
lines[0]=json.dumps(e)+'\n'; open('witness.jsonl','w').writelines(lines)
|
|
149
|
+
"
|
|
150
|
+
|
|
151
|
+
agentwit replay --session ./witness_logs/session_20260314_120000
|
|
152
|
+
# Session: session_20260314_120000 (6 events)
|
|
153
|
+
# Chain integrity: TAMPERED
|
|
154
|
+
# [event 0] FAIL - session_chain mismatch:
|
|
155
|
+
# expected '0fd4d24bcb3dab7d171e…'
|
|
156
|
+
# got 'a79a9e4cdb19795a521e…'
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## ユースケース
|
|
160
|
+
|
|
161
|
+
- **セキュリティエンジニア** — 本番環境でのAIエージェントの挙動を監査
|
|
162
|
+
- **エンタープライズチーム** — AI活動のコンプライアンスログとして保存
|
|
163
|
+
- **AI研究者** — エージェントセッションを再現可能な形式で比較・検証
|
|
164
|
+
- **ペネトレーションテスター** — MCPツール使用状況を証跡として文書化
|
|
165
|
+
|
|
166
|
+
## Python API
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from agentwit import WitnessLogger, ChainManager
|
|
170
|
+
|
|
171
|
+
# プロキシなしで直接ログを記録
|
|
172
|
+
logger = WitnessLogger(session_dir="./logs", actor="my-agent")
|
|
173
|
+
event = logger.log_event(
|
|
174
|
+
action="tools/call",
|
|
175
|
+
tool="bash",
|
|
176
|
+
full_payload={"params": {"command": "ls"}, "result": {"stdout": "..."}}
|
|
177
|
+
)
|
|
178
|
+
logger.close()
|
|
179
|
+
|
|
180
|
+
# 記録済みセッションのChain Integrityを検証
|
|
181
|
+
chain = ChainManager(session_id="session_20260314_120000")
|
|
182
|
+
results = chain.verify_chain(events)
|
|
183
|
+
all_valid = all(r["valid"] for r in results)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 動作要件
|
|
187
|
+
|
|
188
|
+
- Python 3.10+
|
|
189
|
+
- FastAPI, uvicorn, httpx, click(インストール時に自動導入)
|
|
190
|
+
|
|
191
|
+
## ライセンス
|
|
192
|
+
|
|
193
|
+
[MIT](LICENSE) © agentwit contributors
|