athar 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.
- athar-0.1.0/LICENSE +21 -0
- athar-0.1.0/MANIFEST.in +5 -0
- athar-0.1.0/PKG-INFO +236 -0
- athar-0.1.0/README.md +204 -0
- athar-0.1.0/assets/logo-banner.svg +65 -0
- athar-0.1.0/assets/logo-icon.svg +18 -0
- athar-0.1.0/assets/logo.svg +41 -0
- athar-0.1.0/pyproject.toml +63 -0
- athar-0.1.0/setup.cfg +4 -0
- athar-0.1.0/src/athar/__init__.py +25 -0
- athar-0.1.0/src/athar/adapters/crucible_adapter.py +17 -0
- athar-0.1.0/src/athar/core/tracer.py +204 -0
- athar-0.1.0/src/athar/storage/sqlite_store.py +241 -0
- athar-0.1.0/src/athar/ui/app.py +184 -0
- athar-0.1.0/src/athar/ui/static/index.html +732 -0
- athar-0.1.0/src/athar.egg-info/PKG-INFO +236 -0
- athar-0.1.0/src/athar.egg-info/SOURCES.txt +22 -0
- athar-0.1.0/src/athar.egg-info/dependency_links.txt +1 -0
- athar-0.1.0/src/athar.egg-info/entry_points.txt +3 -0
- athar-0.1.0/src/athar.egg-info/requires.txt +9 -0
- athar-0.1.0/src/athar.egg-info/top_level.txt +1 -0
- athar-0.1.0/tests/test_api.py +77 -0
- athar-0.1.0/tests/test_storage.py +82 -0
- athar-0.1.0/tests/test_tracer.py +94 -0
athar-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abdur Rafay
|
|
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.
|
athar-0.1.0/MANIFEST.in
ADDED
athar-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: athar
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A local-first, time-travel debugger for multi-agent LLM systems.
|
|
5
|
+
Author: Abdur-Rafay-AR
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Abdur-Rafay-AR/athar
|
|
8
|
+
Project-URL: Repository, https://github.com/Abdur-Rafay-AR/athar
|
|
9
|
+
Project-URL: Issues, https://github.com/Abdur-Rafay-AR/athar/issues
|
|
10
|
+
Keywords: llm,agents,observability,debugger,time-travel,multi-agent,tracing,local-first
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: fastapi>=0.100.0
|
|
24
|
+
Requires-Dist: uvicorn>=0.23.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: httpx>=0.24.0; extra == "dev"
|
|
29
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
<div align="center">
|
|
34
|
+
|
|
35
|
+
<img src="assets/logo.svg" alt="Athar Logo" width="130" />
|
|
36
|
+
|
|
37
|
+
# athar (أثر)
|
|
38
|
+
|
|
39
|
+
**A local-first, time-travel debugger and observability engine for multi-agent LLM systems.**
|
|
40
|
+
|
|
41
|
+
[](tests/)
|
|
42
|
+
[](https://www.python.org/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](CONTRIBUTING.md)
|
|
45
|
+
[](#architecture)
|
|
46
|
+
|
|
47
|
+
<br />
|
|
48
|
+
|
|
49
|
+
<p align="center">
|
|
50
|
+
<code>fork</code> • <code>edit</code> • <code>replay</code>
|
|
51
|
+
</p>
|
|
52
|
+
|
|
53
|
+
<p align="center">
|
|
54
|
+
<i>No account. No cloud fees. No vendor lock-in. Just SQLite on disk, a sleek local web UI, and instantaneous time-travel replays.</i>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 💡 Why Athar?
|
|
62
|
+
|
|
63
|
+
If you have built anything beyond a single-prompt toy, you've encountered this nightmare:
|
|
64
|
+
|
|
65
|
+
> *Your multi-agent loop fails on step 6 of 10. You add a `print()` statement, re-run the entire pipeline, burn hundreds of thousands of tokens, wait 45 seconds, and... it succeeds this time because LLMs are stochastic.*
|
|
66
|
+
|
|
67
|
+
Existing observability platforms (LangSmith, Phoenix, Langfuse) solve **logging**—you can see what went wrong after the fact. **None of them solve interactive debugging**:
|
|
68
|
+
|
|
69
|
+
- ❌ Re-running from scratch burns money and wastes time.
|
|
70
|
+
- ❌ SaaS observability platforms require sending private prompts, embeddings, and customer data to external cloud vendors.
|
|
71
|
+
- ❌ You cannot easily mutate the state at step 4 and test *“what if the tool returned X instead?”*.
|
|
72
|
+
|
|
73
|
+
### The Athar Solution: **Fork & Replay**
|
|
74
|
+
|
|
75
|
+
Athar records every execution step (prompts, tool calls, tool results, state snapshots) into a local SQLite database using Write-Ahead Logging (WAL).
|
|
76
|
+
|
|
77
|
+
When an agent goes off track:
|
|
78
|
+
1. **Scrub** through the execution timeline in the local web UI.
|
|
79
|
+
2. **Select** the exact step where things went wrong.
|
|
80
|
+
3. **Mutate** the prompt, tool output, or agent state in the inspector.
|
|
81
|
+
4. **Hit Replay**: Athar resumes execution from that step forward. **Prior steps are never re-executed**, saving your API credits and minutes of wait time.
|
|
82
|
+
5. Athar creates a new branch in the trace graph, letting you compare the original vs. mutated paths side-by-side.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## ⚡ 10-Second Quickstart
|
|
87
|
+
|
|
88
|
+
### 1. Installation
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/Abdur-Rafay-AR/athar.git
|
|
92
|
+
cd athar
|
|
93
|
+
pip install -e .
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 2. Instrument Your Code
|
|
97
|
+
|
|
98
|
+
Wrap any agent or tool function with `@traced`:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import asyncio
|
|
102
|
+
from athar import traced, TracerContext
|
|
103
|
+
|
|
104
|
+
@traced
|
|
105
|
+
async def search_tool(query: str):
|
|
106
|
+
# Simulating a search tool or API lookup
|
|
107
|
+
await asyncio.sleep(0.2)
|
|
108
|
+
return {"results": f"Found latest data for: {query}"}
|
|
109
|
+
|
|
110
|
+
@traced
|
|
111
|
+
async def research_agent(topic: str):
|
|
112
|
+
print(f"Researching: {topic}")
|
|
113
|
+
data = await search_tool(topic)
|
|
114
|
+
return f"Synthesized report based on {data['results']}"
|
|
115
|
+
|
|
116
|
+
async def main():
|
|
117
|
+
# Bundle execution inside a named trace session
|
|
118
|
+
async with TracerContext(name="Market Intelligence Run"):
|
|
119
|
+
report = await research_agent("Autonomous Coding Agents")
|
|
120
|
+
print("Done:", report)
|
|
121
|
+
|
|
122
|
+
if __name__ == "__main__":
|
|
123
|
+
asyncio.run(main())
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 3. Open the Athar Debugger UI
|
|
127
|
+
|
|
128
|
+
Start the local server:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
athar
|
|
132
|
+
```
|
|
133
|
+
*(Or run `run-local.cmd` on Windows).*
|
|
134
|
+
|
|
135
|
+
Open **[http://localhost:4173](http://localhost:4173)** to scrub through steps, inspect inputs/outputs, and initiate time-travel replays!
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🏛️ Architecture
|
|
140
|
+
|
|
141
|
+
```mermaid
|
|
142
|
+
flowchart TD
|
|
143
|
+
subgraph AgentApp["Your Agent Application"]
|
|
144
|
+
A["Agent Orchestrator"] --> B["Tool Calls & LLM Queries"]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
subgraph AtharSDK["Athar SDK (Instrumentation)"]
|
|
148
|
+
T["@traced / TracerContext"]
|
|
149
|
+
H["SHA-256 Content Hasher"]
|
|
150
|
+
C["ContextVar Call Tree Tracker"]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
subgraph Storage["Local Storage Layer"]
|
|
154
|
+
DB[("SQLite WAL Store\nagent_traces.db")]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
subgraph WebUI["Athar Web UI (FastAPI)"]
|
|
158
|
+
UI["Interactive Timeline & DAG Inspector"]
|
|
159
|
+
FR["Fork & Replay State Mutator"]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
AgentApp -->|wraps execution| AtharSDK
|
|
163
|
+
AtharSDK -->|async WAL writes| Storage
|
|
164
|
+
Storage <-->|reads & branches| WebUI
|
|
165
|
+
FR -.->|re-executes branch| AgentApp
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### System Architecture Highlights
|
|
169
|
+
|
|
170
|
+
- **SQLite WAL Mode**: Thread-safe, non-blocking concurrent writes from high-throughput agent loops while the Web UI live-polls data.
|
|
171
|
+
- **Deterministic Content Hashing**: Every step generates a SHA-256 fingerprint based on inputs, state, and function signatures.
|
|
172
|
+
- **ContextVar Hierarchy Chaining**: Automatically preserves parent-child relationships across nested agent calls and async tasks without messy manual span propagation.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## ✨ Features
|
|
177
|
+
|
|
178
|
+
- 🌿 **Time-Travel Fork & Replay**: Edit inputs or state snapshots at any node and re-execute downstream steps without re-running earlier nodes.
|
|
179
|
+
- 🔒 **100% Local & Private**: No cloud credentials, zero telemetry, no external database dependencies. Your sensitive prompts and proprietary agent code never leave your machine.
|
|
180
|
+
- ⚡ **Zero-Overhead Instrumentation**: Drop-in `@traced` decorator and `TracerContext` context manager with negligible runtime impact.
|
|
181
|
+
- 📊 **Step Inspector**: Real-time view of inputs, arguments, outputs, errors, latency, and cost per step.
|
|
182
|
+
- 🔌 **Framework Agnostic**: Works out of the box with raw Python loops, LangChain, AutoGen, CrewAI, and Crucible.
|
|
183
|
+
- 🎨 **Modern Dark-Mode UI**: Built with a clean aesthetic, interactive timeline cards, and in-browser state mutation editor.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 🖥️ CLI Commands
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Launch Athar UI on default port 4173
|
|
191
|
+
athar
|
|
192
|
+
|
|
193
|
+
# Launch on custom port and host
|
|
194
|
+
athar --port 8080 --host 0.0.0.0
|
|
195
|
+
|
|
196
|
+
# Point to a custom SQLite database file
|
|
197
|
+
athar --db ./path/to/my_traces.db
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 🛠️ Development & Testing
|
|
203
|
+
|
|
204
|
+
We welcome contributions! Run the automated test suite with Python's built-in `unittest` or `pytest`:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Install with dev dependencies
|
|
208
|
+
pip install -e ".[dev]"
|
|
209
|
+
|
|
210
|
+
# Run tests
|
|
211
|
+
python -m unittest discover -s tests
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details on development workflows, adapters, and style guidelines.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 🗺️ Roadmap
|
|
219
|
+
|
|
220
|
+
- [x] **v0.1**: Local-first tracer SDK, SQLite WAL store, FastAPI server, interactive timeline UI, fork & replay mechanics.
|
|
221
|
+
- [ ] **v0.2**: Side-by-side branch diff visualizer (compare outputs, cost differences, and token latency between two forks).
|
|
222
|
+
- [ ] **v0.3**: Native adapters for LangChain callback handlers and AutoGen conversation listeners.
|
|
223
|
+
- [ ] **v0.4**: Live trace streaming via WebSockets / Server-Sent Events (SSE).
|
|
224
|
+
- [ ] **v1.0**: Stable SDK API, export traces to OpenTelemetry, and team sharing utilities.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 📜 Meaning of "Athar"
|
|
229
|
+
|
|
230
|
+
**Athar** (أثر) is an Arabic word meaning **trace**, **imprint**, or **footprint**. In agentic AI systems, understanding the exact trace left behind by an agent's reasoning process is the key to mastering reliability, interpretability, and deterministic debugging.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 📄 License
|
|
235
|
+
|
|
236
|
+
Distributed under the [MIT License](LICENSE). Copyright © 2026 Abdur Rafay.
|
athar-0.1.0/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/logo.svg" alt="Athar Logo" width="130" />
|
|
4
|
+
|
|
5
|
+
# athar (أثر)
|
|
6
|
+
|
|
7
|
+
**A local-first, time-travel debugger and observability engine for multi-agent LLM systems.**
|
|
8
|
+
|
|
9
|
+
[](tests/)
|
|
10
|
+
[](https://www.python.org/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](CONTRIBUTING.md)
|
|
13
|
+
[](#architecture)
|
|
14
|
+
|
|
15
|
+
<br />
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<code>fork</code> • <code>edit</code> • <code>replay</code>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<i>No account. No cloud fees. No vendor lock-in. Just SQLite on disk, a sleek local web UI, and instantaneous time-travel replays.</i>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 💡 Why Athar?
|
|
30
|
+
|
|
31
|
+
If you have built anything beyond a single-prompt toy, you've encountered this nightmare:
|
|
32
|
+
|
|
33
|
+
> *Your multi-agent loop fails on step 6 of 10. You add a `print()` statement, re-run the entire pipeline, burn hundreds of thousands of tokens, wait 45 seconds, and... it succeeds this time because LLMs are stochastic.*
|
|
34
|
+
|
|
35
|
+
Existing observability platforms (LangSmith, Phoenix, Langfuse) solve **logging**—you can see what went wrong after the fact. **None of them solve interactive debugging**:
|
|
36
|
+
|
|
37
|
+
- ❌ Re-running from scratch burns money and wastes time.
|
|
38
|
+
- ❌ SaaS observability platforms require sending private prompts, embeddings, and customer data to external cloud vendors.
|
|
39
|
+
- ❌ You cannot easily mutate the state at step 4 and test *“what if the tool returned X instead?”*.
|
|
40
|
+
|
|
41
|
+
### The Athar Solution: **Fork & Replay**
|
|
42
|
+
|
|
43
|
+
Athar records every execution step (prompts, tool calls, tool results, state snapshots) into a local SQLite database using Write-Ahead Logging (WAL).
|
|
44
|
+
|
|
45
|
+
When an agent goes off track:
|
|
46
|
+
1. **Scrub** through the execution timeline in the local web UI.
|
|
47
|
+
2. **Select** the exact step where things went wrong.
|
|
48
|
+
3. **Mutate** the prompt, tool output, or agent state in the inspector.
|
|
49
|
+
4. **Hit Replay**: Athar resumes execution from that step forward. **Prior steps are never re-executed**, saving your API credits and minutes of wait time.
|
|
50
|
+
5. Athar creates a new branch in the trace graph, letting you compare the original vs. mutated paths side-by-side.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## ⚡ 10-Second Quickstart
|
|
55
|
+
|
|
56
|
+
### 1. Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/Abdur-Rafay-AR/athar.git
|
|
60
|
+
cd athar
|
|
61
|
+
pip install -e .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Instrument Your Code
|
|
65
|
+
|
|
66
|
+
Wrap any agent or tool function with `@traced`:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import asyncio
|
|
70
|
+
from athar import traced, TracerContext
|
|
71
|
+
|
|
72
|
+
@traced
|
|
73
|
+
async def search_tool(query: str):
|
|
74
|
+
# Simulating a search tool or API lookup
|
|
75
|
+
await asyncio.sleep(0.2)
|
|
76
|
+
return {"results": f"Found latest data for: {query}"}
|
|
77
|
+
|
|
78
|
+
@traced
|
|
79
|
+
async def research_agent(topic: str):
|
|
80
|
+
print(f"Researching: {topic}")
|
|
81
|
+
data = await search_tool(topic)
|
|
82
|
+
return f"Synthesized report based on {data['results']}"
|
|
83
|
+
|
|
84
|
+
async def main():
|
|
85
|
+
# Bundle execution inside a named trace session
|
|
86
|
+
async with TracerContext(name="Market Intelligence Run"):
|
|
87
|
+
report = await research_agent("Autonomous Coding Agents")
|
|
88
|
+
print("Done:", report)
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
asyncio.run(main())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 3. Open the Athar Debugger UI
|
|
95
|
+
|
|
96
|
+
Start the local server:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
athar
|
|
100
|
+
```
|
|
101
|
+
*(Or run `run-local.cmd` on Windows).*
|
|
102
|
+
|
|
103
|
+
Open **[http://localhost:4173](http://localhost:4173)** to scrub through steps, inspect inputs/outputs, and initiate time-travel replays!
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🏛️ Architecture
|
|
108
|
+
|
|
109
|
+
```mermaid
|
|
110
|
+
flowchart TD
|
|
111
|
+
subgraph AgentApp["Your Agent Application"]
|
|
112
|
+
A["Agent Orchestrator"] --> B["Tool Calls & LLM Queries"]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
subgraph AtharSDK["Athar SDK (Instrumentation)"]
|
|
116
|
+
T["@traced / TracerContext"]
|
|
117
|
+
H["SHA-256 Content Hasher"]
|
|
118
|
+
C["ContextVar Call Tree Tracker"]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
subgraph Storage["Local Storage Layer"]
|
|
122
|
+
DB[("SQLite WAL Store\nagent_traces.db")]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
subgraph WebUI["Athar Web UI (FastAPI)"]
|
|
126
|
+
UI["Interactive Timeline & DAG Inspector"]
|
|
127
|
+
FR["Fork & Replay State Mutator"]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
AgentApp -->|wraps execution| AtharSDK
|
|
131
|
+
AtharSDK -->|async WAL writes| Storage
|
|
132
|
+
Storage <-->|reads & branches| WebUI
|
|
133
|
+
FR -.->|re-executes branch| AgentApp
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### System Architecture Highlights
|
|
137
|
+
|
|
138
|
+
- **SQLite WAL Mode**: Thread-safe, non-blocking concurrent writes from high-throughput agent loops while the Web UI live-polls data.
|
|
139
|
+
- **Deterministic Content Hashing**: Every step generates a SHA-256 fingerprint based on inputs, state, and function signatures.
|
|
140
|
+
- **ContextVar Hierarchy Chaining**: Automatically preserves parent-child relationships across nested agent calls and async tasks without messy manual span propagation.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## ✨ Features
|
|
145
|
+
|
|
146
|
+
- 🌿 **Time-Travel Fork & Replay**: Edit inputs or state snapshots at any node and re-execute downstream steps without re-running earlier nodes.
|
|
147
|
+
- 🔒 **100% Local & Private**: No cloud credentials, zero telemetry, no external database dependencies. Your sensitive prompts and proprietary agent code never leave your machine.
|
|
148
|
+
- ⚡ **Zero-Overhead Instrumentation**: Drop-in `@traced` decorator and `TracerContext` context manager with negligible runtime impact.
|
|
149
|
+
- 📊 **Step Inspector**: Real-time view of inputs, arguments, outputs, errors, latency, and cost per step.
|
|
150
|
+
- 🔌 **Framework Agnostic**: Works out of the box with raw Python loops, LangChain, AutoGen, CrewAI, and Crucible.
|
|
151
|
+
- 🎨 **Modern Dark-Mode UI**: Built with a clean aesthetic, interactive timeline cards, and in-browser state mutation editor.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 🖥️ CLI Commands
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Launch Athar UI on default port 4173
|
|
159
|
+
athar
|
|
160
|
+
|
|
161
|
+
# Launch on custom port and host
|
|
162
|
+
athar --port 8080 --host 0.0.0.0
|
|
163
|
+
|
|
164
|
+
# Point to a custom SQLite database file
|
|
165
|
+
athar --db ./path/to/my_traces.db
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 🛠️ Development & Testing
|
|
171
|
+
|
|
172
|
+
We welcome contributions! Run the automated test suite with Python's built-in `unittest` or `pytest`:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Install with dev dependencies
|
|
176
|
+
pip install -e ".[dev]"
|
|
177
|
+
|
|
178
|
+
# Run tests
|
|
179
|
+
python -m unittest discover -s tests
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details on development workflows, adapters, and style guidelines.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 🗺️ Roadmap
|
|
187
|
+
|
|
188
|
+
- [x] **v0.1**: Local-first tracer SDK, SQLite WAL store, FastAPI server, interactive timeline UI, fork & replay mechanics.
|
|
189
|
+
- [ ] **v0.2**: Side-by-side branch diff visualizer (compare outputs, cost differences, and token latency between two forks).
|
|
190
|
+
- [ ] **v0.3**: Native adapters for LangChain callback handlers and AutoGen conversation listeners.
|
|
191
|
+
- [ ] **v0.4**: Live trace streaming via WebSockets / Server-Sent Events (SSE).
|
|
192
|
+
- [ ] **v1.0**: Stable SDK API, export traces to OpenTelemetry, and team sharing utilities.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 📜 Meaning of "Athar"
|
|
197
|
+
|
|
198
|
+
**Athar** (أثر) is an Arabic word meaning **trace**, **imprint**, or **footprint**. In agentic AI systems, understanding the exact trace left behind by an agent's reasoning process is the key to mastering reliability, interpretability, and deterministic debugging.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 📄 License
|
|
203
|
+
|
|
204
|
+
Distributed under the [MIT License](LICENSE). Copyright © 2026 Abdur Rafay.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="220" viewBox="0 0 880 220" fill="none" role="img" aria-label="Athar Banner">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="banner-glow" cx="18%" cy="50%" r="55%">
|
|
4
|
+
<stop offset="0%" stop-color="#163140" stop-opacity="0.9"/>
|
|
5
|
+
<stop offset="60%" stop-color="#101820" stop-opacity="1"/>
|
|
6
|
+
<stop offset="100%" stop-color="#090e13" stop-opacity="1"/>
|
|
7
|
+
</radialGradient>
|
|
8
|
+
<filter id="banner-teal-glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
9
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur"/>
|
|
10
|
+
<feMerge>
|
|
11
|
+
<feMergeNode in="blur"/>
|
|
12
|
+
<feMergeNode in="SourceGraphic"/>
|
|
13
|
+
</feMerge>
|
|
14
|
+
</filter>
|
|
15
|
+
<linearGradient id="banner-line-grad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
16
|
+
<stop offset="0%" stop-color="#FFFFFF"/>
|
|
17
|
+
<stop offset="100%" stop-color="#C2D3DE"/>
|
|
18
|
+
</linearGradient>
|
|
19
|
+
</defs>
|
|
20
|
+
|
|
21
|
+
<!-- Background container -->
|
|
22
|
+
<rect width="880" height="220" rx="20" fill="url(#banner-glow)"/>
|
|
23
|
+
<rect width="878" height="218" x="1" y="1" rx="19" stroke="#1d3442" stroke-width="1.2" fill="none"/>
|
|
24
|
+
|
|
25
|
+
<!-- Left: Emblem / Trace Mark -->
|
|
26
|
+
<g transform="translate(60, 42)">
|
|
27
|
+
<path d="M68 16 V55 M68 55 L32 96 M68 55 V104 M68 55 L104 96"
|
|
28
|
+
stroke="url(#banner-line-grad)" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
29
|
+
<circle cx="68" cy="14" r="6.5" fill="#00D6A3" filter="url(#banner-teal-glow)"/>
|
|
30
|
+
<circle cx="68" cy="55" r="5.5" fill="#00D6A3" stroke="#101820" stroke-width="2.5" filter="url(#banner-teal-glow)"/>
|
|
31
|
+
<circle cx="32" cy="98" r="6.5" fill="#00D6A3" filter="url(#banner-teal-glow)"/>
|
|
32
|
+
<circle cx="68" cy="106" r="6.5" fill="#00D6A3" filter="url(#banner-teal-glow)"/>
|
|
33
|
+
<circle cx="104" cy="98" r="6.5" fill="#00D6A3" filter="url(#banner-teal-glow)"/>
|
|
34
|
+
</g>
|
|
35
|
+
|
|
36
|
+
<!-- Right: Title, Slogan, and Details -->
|
|
37
|
+
<g transform="translate(230, 48)">
|
|
38
|
+
<!-- Brand Title -->
|
|
39
|
+
<text x="0" y="44"
|
|
40
|
+
font-family="'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
41
|
+
font-size="48" font-weight="700" letter-spacing="0.02em" fill="#F4F7FA">athar</text>
|
|
42
|
+
|
|
43
|
+
<!-- Tagline pill -->
|
|
44
|
+
<rect x="140" y="16" width="168" height="26" rx="13" fill="#172b38" stroke="#00D6A3" stroke-opacity="0.35" stroke-width="1"/>
|
|
45
|
+
<text x="224" y="33" text-anchor="middle"
|
|
46
|
+
font-family="'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
47
|
+
font-size="11" font-weight="600" letter-spacing="0.1em" fill="#00D6A3">FORK · EDIT · REPLAY</text>
|
|
48
|
+
|
|
49
|
+
<!-- Subtitle -->
|
|
50
|
+
<text x="0" y="80"
|
|
51
|
+
font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
52
|
+
font-size="16" font-weight="400" fill="#B3C4D0">
|
|
53
|
+
Local-first, time-travel debugger & observability for multi-agent LLM systems.
|
|
54
|
+
</text>
|
|
55
|
+
|
|
56
|
+
<!-- Feature badges line -->
|
|
57
|
+
<g transform="translate(0, 102)">
|
|
58
|
+
<text x="0" y="14"
|
|
59
|
+
font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
60
|
+
font-size="12.5" font-weight="500" fill="#7E96A6">
|
|
61
|
+
✔ Zero Cloud Lock-in • ✔ SQLite Local Tracing • ✔ Interactive Visual Timeline
|
|
62
|
+
</text>
|
|
63
|
+
</g>
|
|
64
|
+
</g>
|
|
65
|
+
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="136" height="136" viewBox="0 0 136 136" fill="none" role="img" aria-label="Athar Icon">
|
|
2
|
+
<defs>
|
|
3
|
+
<filter id="icon-glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
4
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"/>
|
|
5
|
+
<feMerge>
|
|
6
|
+
<feMergeNode in="blur"/>
|
|
7
|
+
<feMergeNode in="SourceGraphic"/>
|
|
8
|
+
</feMerge>
|
|
9
|
+
</filter>
|
|
10
|
+
</defs>
|
|
11
|
+
<path d="M68 16 V55 M68 55 L32 96 M68 55 V104 M68 55 L104 96"
|
|
12
|
+
stroke="#F4F7FA" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
13
|
+
<circle cx="68" cy="14" r="6.5" fill="#00D6A3" filter="url(#icon-glow)"/>
|
|
14
|
+
<circle cx="68" cy="55" r="5.5" fill="#00D6A3" stroke="#101820" stroke-width="2.5" filter="url(#icon-glow)"/>
|
|
15
|
+
<circle cx="32" cy="98" r="6.5" fill="#00D6A3" filter="url(#icon-glow)"/>
|
|
16
|
+
<circle cx="68" cy="106" r="6.5" fill="#00D6A3" filter="url(#icon-glow)"/>
|
|
17
|
+
<circle cx="104" cy="98" r="6.5" fill="#00D6A3" filter="url(#icon-glow)"/>
|
|
18
|
+
</svg>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" fill="none" role="img" aria-label="Athar Logo">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="athar-bg" cx="50%" cy="40%" r="65%">
|
|
4
|
+
<stop offset="0%" stop-color="#162c38"/>
|
|
5
|
+
<stop offset="55%" stop-color="#101820"/>
|
|
6
|
+
<stop offset="100%" stop-color="#090e13"/>
|
|
7
|
+
</radialGradient>
|
|
8
|
+
<filter id="teal-glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
9
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="3.5" result="blur"/>
|
|
10
|
+
<feMerge>
|
|
11
|
+
<feMergeNode in="blur"/>
|
|
12
|
+
<feMergeNode in="SourceGraphic"/>
|
|
13
|
+
</feMerge>
|
|
14
|
+
</filter>
|
|
15
|
+
<linearGradient id="trace-line-grad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
16
|
+
<stop offset="0%" stop-color="#FFFFFF"/>
|
|
17
|
+
<stop offset="100%" stop-color="#C2D3DE"/>
|
|
18
|
+
</linearGradient>
|
|
19
|
+
</defs>
|
|
20
|
+
|
|
21
|
+
<!-- Sleek rounded squircle container -->
|
|
22
|
+
<rect width="200" height="200" rx="44" fill="url(#athar-bg)"/>
|
|
23
|
+
<rect width="198" height="198" x="1" y="1" rx="43" stroke="#1d3442" stroke-width="1.5" fill="none"/>
|
|
24
|
+
|
|
25
|
+
<!-- Trace DAG Symbol (Centered, Pure Mark Only) -->
|
|
26
|
+
<g transform="translate(15, 25) scale(1.25)">
|
|
27
|
+
<!-- Branching paths -->
|
|
28
|
+
<path d="M68 16 V55 M68 55 L32 96 M68 55 V104 M68 55 L104 96"
|
|
29
|
+
stroke="url(#trace-line-grad)" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
30
|
+
|
|
31
|
+
<!-- Glowing connection nodes -->
|
|
32
|
+
<!-- Root node -->
|
|
33
|
+
<circle cx="68" cy="14" r="6.5" fill="#00D6A3" filter="url(#teal-glow)"/>
|
|
34
|
+
<!-- Fork decision node -->
|
|
35
|
+
<circle cx="68" cy="55" r="5.5" fill="#00D6A3" stroke="#101820" stroke-width="2.5" filter="url(#teal-glow)"/>
|
|
36
|
+
<!-- Branch leaves -->
|
|
37
|
+
<circle cx="32" cy="98" r="6.5" fill="#00D6A3" filter="url(#teal-glow)"/>
|
|
38
|
+
<circle cx="68" cy="106" r="6.5" fill="#00D6A3" filter="url(#teal-glow)"/>
|
|
39
|
+
<circle cx="104" cy="98" r="6.5" fill="#00D6A3" filter="url(#teal-glow)"/>
|
|
40
|
+
</g>
|
|
41
|
+
</svg>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "athar"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A local-first, time-travel debugger for multi-agent LLM systems."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Abdur-Rafay-AR" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"llm",
|
|
17
|
+
"agents",
|
|
18
|
+
"observability",
|
|
19
|
+
"debugger",
|
|
20
|
+
"time-travel",
|
|
21
|
+
"multi-agent",
|
|
22
|
+
"tracing",
|
|
23
|
+
"local-first"
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 4 - Beta",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"Topic :: Software Development :: Debuggers",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.9",
|
|
31
|
+
"Programming Language :: Python :: 3.10",
|
|
32
|
+
"Programming Language :: Python :: 3.11",
|
|
33
|
+
"Programming Language :: Python :: 3.12",
|
|
34
|
+
"Operating System :: OS Independent",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
"fastapi>=0.100.0",
|
|
38
|
+
"uvicorn>=0.23.0",
|
|
39
|
+
"pydantic>=2.0.0"
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = [
|
|
44
|
+
"pytest>=7.0.0",
|
|
45
|
+
"httpx>=0.24.0",
|
|
46
|
+
"build>=1.0.0",
|
|
47
|
+
"twine>=5.0.0"
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[project.scripts]
|
|
51
|
+
athar = "athar.ui.app:main"
|
|
52
|
+
agent-tracer = "athar.ui.app:main"
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://github.com/Abdur-Rafay-AR/athar"
|
|
56
|
+
Repository = "https://github.com/Abdur-Rafay-AR/athar"
|
|
57
|
+
Issues = "https://github.com/Abdur-Rafay-AR/athar/issues"
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.packages.find]
|
|
60
|
+
where = ["src"]
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.package-data]
|
|
63
|
+
"athar.ui" = ["static/*", "static/**/*"]
|
athar-0.1.0/setup.cfg
ADDED