cartha-sdk 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maulik Jadav / Cartha
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,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: cartha-sdk
3
+ Version: 0.1.0
4
+ Summary: Cartha SDK — memory, traces, costs, and policies for AI agents
5
+ Author-email: Maulik Jadav <maulikjadav239@gmail.com>
6
+ Maintainer-email: Maulik Jadav <maulikjadav239@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://cartha.in
9
+ Project-URL: Documentation, https://cartha.in
10
+ Project-URL: Repository, https://github.com/maulik-jadav/nexus
11
+ Project-URL: Issues, https://github.com/maulik-jadav/nexus/issues
12
+ Project-URL: Source, https://github.com/maulik-jadav/nexus/tree/main/nexus/packages/sdk-python
13
+ Keywords: cartha,agents,llm,observability,tracing,memory,ai
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx>=0.27
27
+ Dynamic: license-file
28
+
29
+ # Cartha SDK (Python)
30
+
31
+ Instrument AI agents with memory, traces, costs, and policies on [Cartha](https://cartha.in).
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install cartha-sdk
37
+ ```
38
+
39
+ Requires Python 3.10+.
40
+
41
+ From source (development):
42
+
43
+ ```bash
44
+ pip install "git+https://github.com/maulik-jadav/nexus.git#subdirectory=nexus/packages/sdk-python"
45
+ # or from a local clone:
46
+ pip install -e nexus/packages/sdk-python
47
+ ```
48
+
49
+ ## Quickstart
50
+
51
+ ```bash
52
+ export CARTHA_API_KEY="cartha_..." # from the dashboard → Keys
53
+ export CARTHA_API_BASE="https://cartha.in" # your Cartha deployment
54
+ ```
55
+
56
+ ```python
57
+ import cartha
58
+
59
+ cartha.init() # picks up CARTHA_* env vars
60
+
61
+ @cartha.trace()
62
+ def run_agent(prompt: str):
63
+ return "..."
64
+ ```
65
+
66
+ `@cartha.trace()` works on sync and async functions. Every call registers the
67
+ agent, sends heartbeats, and records a full trace (start → steps → finish),
68
+ including failures.
69
+
70
+ ## Memory
71
+
72
+ ```python
73
+ import cartha
74
+
75
+ # async agents
76
+ await cartha.remember(user_id="u1", content="Prefers dark mode", scope="user")
77
+ hits = await cartha.recall(user_id="u1", context="UI preferences", scope=["user", "team"])
78
+
79
+ # sync code
80
+ cartha.remember_sync(user_id="u1", content="Prefers dark mode", scope="user")
81
+ ```
82
+
83
+ Scopes: `agent` (private) · `user` (all agents serving that user) ·
84
+ `team` (same `team_id`) · `org` (everyone in your org).
85
+
86
+ ## Nested agents (multi-agent loops)
87
+
88
+ By default, `@cartha.trace()` **auto-nests**: if a traced agent calls another
89
+ traced agent, the child run links via `parent_trace_id`. No env plumbing
90
+ required for in-process sub-agents.
91
+
92
+ ```python
93
+ @cartha.trace(id="parent")
94
+ async def orchestrator(user_id: str):
95
+ await cartha.ops.delegate(to_agent_id="worker", task_description="handle")
96
+ return await worker(user_id)
97
+
98
+ @cartha.trace(id="worker") # nests under orchestrator automatically
99
+ async def worker(user_id: str):
100
+ ...
101
+ ```
102
+
103
+ ## Cost per completed task
104
+
105
+ Share a `task_id` across retries so the dashboard rolls failed redoes into one outcome:
106
+
107
+ ```python
108
+ tid = cartha.task_context()
109
+ for attempt in range(3):
110
+ try:
111
+ await run_agent(..., cartha_task_id=tid)
112
+ break
113
+ except Exception:
114
+ continue
115
+ ```
116
+
117
+ ## Memory denial mode
118
+
119
+ Org setting (`PATCH /org` → `memory_denial_mode`):
120
+
121
+ - `denied_hint` (default): recall returns explicit denials without content so agents don't invent over a hole.
122
+ - `silent`: empty hits only (no existence leak).
123
+
124
+ ## Advanced
125
+
126
+ The full instrumentation API lives in `cartha.ops` (tool calls, cost events,
127
+ A2A delegation, policy checks, run nesting):
128
+
129
+ ```python
130
+ from cartha import ops
131
+ ```
132
+
133
+ **Legacy alias:** older code may `from nexus import ops`. That still works for
134
+ compatibility, but new code should use `cartha`.
135
+
136
+ **Trace diff:** `GET /api/v1/traces/diff?left=…&right=…` finds the first
137
+ diverging step between two runs (also on the dashboard).
138
+
139
+ ## Publishing (maintainers)
140
+
141
+ Releases are published from GitHub Actions when you push a tag matching
142
+ `sdk-python-v*` (for example `sdk-python-v0.1.0`).
143
+
144
+ Manual upload (emergency / first release):
145
+
146
+ ```bash
147
+ cd nexus/packages/sdk-python
148
+ python -m pip install --upgrade build twine
149
+ python -m build
150
+ # TestPyPI first (recommended):
151
+ python -m twine upload --repository testpypi dist/*
152
+ # Production PyPI:
153
+ python -m twine upload dist/*
154
+ ```
155
+
156
+ Use a PyPI API token (`pypi-...`), not your account password.
@@ -0,0 +1,128 @@
1
+ # Cartha SDK (Python)
2
+
3
+ Instrument AI agents with memory, traces, costs, and policies on [Cartha](https://cartha.in).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install cartha-sdk
9
+ ```
10
+
11
+ Requires Python 3.10+.
12
+
13
+ From source (development):
14
+
15
+ ```bash
16
+ pip install "git+https://github.com/maulik-jadav/nexus.git#subdirectory=nexus/packages/sdk-python"
17
+ # or from a local clone:
18
+ pip install -e nexus/packages/sdk-python
19
+ ```
20
+
21
+ ## Quickstart
22
+
23
+ ```bash
24
+ export CARTHA_API_KEY="cartha_..." # from the dashboard → Keys
25
+ export CARTHA_API_BASE="https://cartha.in" # your Cartha deployment
26
+ ```
27
+
28
+ ```python
29
+ import cartha
30
+
31
+ cartha.init() # picks up CARTHA_* env vars
32
+
33
+ @cartha.trace()
34
+ def run_agent(prompt: str):
35
+ return "..."
36
+ ```
37
+
38
+ `@cartha.trace()` works on sync and async functions. Every call registers the
39
+ agent, sends heartbeats, and records a full trace (start → steps → finish),
40
+ including failures.
41
+
42
+ ## Memory
43
+
44
+ ```python
45
+ import cartha
46
+
47
+ # async agents
48
+ await cartha.remember(user_id="u1", content="Prefers dark mode", scope="user")
49
+ hits = await cartha.recall(user_id="u1", context="UI preferences", scope=["user", "team"])
50
+
51
+ # sync code
52
+ cartha.remember_sync(user_id="u1", content="Prefers dark mode", scope="user")
53
+ ```
54
+
55
+ Scopes: `agent` (private) · `user` (all agents serving that user) ·
56
+ `team` (same `team_id`) · `org` (everyone in your org).
57
+
58
+ ## Nested agents (multi-agent loops)
59
+
60
+ By default, `@cartha.trace()` **auto-nests**: if a traced agent calls another
61
+ traced agent, the child run links via `parent_trace_id`. No env plumbing
62
+ required for in-process sub-agents.
63
+
64
+ ```python
65
+ @cartha.trace(id="parent")
66
+ async def orchestrator(user_id: str):
67
+ await cartha.ops.delegate(to_agent_id="worker", task_description="handle")
68
+ return await worker(user_id)
69
+
70
+ @cartha.trace(id="worker") # nests under orchestrator automatically
71
+ async def worker(user_id: str):
72
+ ...
73
+ ```
74
+
75
+ ## Cost per completed task
76
+
77
+ Share a `task_id` across retries so the dashboard rolls failed redoes into one outcome:
78
+
79
+ ```python
80
+ tid = cartha.task_context()
81
+ for attempt in range(3):
82
+ try:
83
+ await run_agent(..., cartha_task_id=tid)
84
+ break
85
+ except Exception:
86
+ continue
87
+ ```
88
+
89
+ ## Memory denial mode
90
+
91
+ Org setting (`PATCH /org` → `memory_denial_mode`):
92
+
93
+ - `denied_hint` (default): recall returns explicit denials without content so agents don't invent over a hole.
94
+ - `silent`: empty hits only (no existence leak).
95
+
96
+ ## Advanced
97
+
98
+ The full instrumentation API lives in `cartha.ops` (tool calls, cost events,
99
+ A2A delegation, policy checks, run nesting):
100
+
101
+ ```python
102
+ from cartha import ops
103
+ ```
104
+
105
+ **Legacy alias:** older code may `from nexus import ops`. That still works for
106
+ compatibility, but new code should use `cartha`.
107
+
108
+ **Trace diff:** `GET /api/v1/traces/diff?left=…&right=…` finds the first
109
+ diverging step between two runs (also on the dashboard).
110
+
111
+ ## Publishing (maintainers)
112
+
113
+ Releases are published from GitHub Actions when you push a tag matching
114
+ `sdk-python-v*` (for example `sdk-python-v0.1.0`).
115
+
116
+ Manual upload (emergency / first release):
117
+
118
+ ```bash
119
+ cd nexus/packages/sdk-python
120
+ python -m pip install --upgrade build twine
121
+ python -m build
122
+ # TestPyPI first (recommended):
123
+ python -m twine upload --repository testpypi dist/*
124
+ # Production PyPI:
125
+ python -m twine upload dist/*
126
+ ```
127
+
128
+ Use a PyPI API token (`pypi-...`), not your account password.
@@ -0,0 +1,142 @@
1
+ """
2
+ Cartha SDK — instrument AI agents with memory, traces, costs, and policies.
3
+
4
+ Quickstart (mirrors the dashboard Settings page):
5
+
6
+ export CARTHA_API_KEY="cartha_..."
7
+ export CARTHA_API_BASE="https://cartha.in"
8
+
9
+ import cartha
10
+ cartha.init()
11
+
12
+ @cartha.trace()
13
+ def run_agent(prompt: str):
14
+ return "..."
15
+
16
+ `cartha.trace()` works on both sync and async functions. Async functions keep
17
+ their full signature and are awaited as usual; sync functions are executed
18
+ through the same instrumentation pipeline via a private event loop.
19
+
20
+ Advanced users can access the underlying instrumentation API directly:
21
+
22
+ from cartha import ops
23
+ await ops.remember(...)
24
+ await ops.recall(...)
25
+ """
26
+ from __future__ import annotations
27
+
28
+ import asyncio
29
+ import os
30
+ from typing import Any, Callable, Literal
31
+
32
+ from nexus import ops
33
+ from nexus.ops import ( # noqa: F401 — re-exported public API
34
+ PolicyViolation,
35
+ cost,
36
+ cost_sync,
37
+ delegate,
38
+ delegate_sync,
39
+ propagation_context,
40
+ recall,
41
+ recall_sync,
42
+ remember,
43
+ remember_sync,
44
+ task_context,
45
+ tool_call,
46
+ tool_call_sync,
47
+ )
48
+
49
+ __all__ = [
50
+ "init",
51
+ "trace",
52
+ "ops",
53
+ "PolicyViolation",
54
+ "recall", "remember", "tool_call", "cost", "delegate", "propagation_context",
55
+ "task_context",
56
+ "recall_sync", "remember_sync", "tool_call_sync", "cost_sync", "delegate_sync",
57
+ ]
58
+
59
+ __version__ = "0.1.0"
60
+
61
+
62
+ def init(
63
+ api_key: str | None = None,
64
+ api_base: str | None = None,
65
+ org_id: str | None = None,
66
+ ) -> None:
67
+ """
68
+ Configure the SDK. Values are resolved in priority order:
69
+ explicit argument > CARTHA_* env var > existing NEXUS_* env var.
70
+
71
+ Safe to call multiple times; later calls override earlier ones.
72
+ """
73
+ key = api_key or os.getenv("CARTHA_API_KEY")
74
+ if key:
75
+ os.environ["NEXUS_API_KEY"] = key
76
+
77
+ base = api_base or os.getenv("CARTHA_API_BASE")
78
+ if base:
79
+ os.environ["NEXUS_ENDPOINT"] = base.rstrip("/")
80
+
81
+ org = org_id or os.getenv("CARTHA_ORG_ID")
82
+ if org:
83
+ os.environ["NEXUS_ORG_ID"] = org
84
+
85
+
86
+ def trace(
87
+ id: str | None = None,
88
+ *,
89
+ team: str | None = None,
90
+ org: str | None = None,
91
+ protocols: list[Literal["mcp", "a2a"]] | None = None,
92
+ description: str = "",
93
+ task_id: str | None = None,
94
+ nest: bool = True,
95
+ ) -> Callable:
96
+ """
97
+ Instrument an agent function: registration, heartbeats, trace
98
+ start/steps/finish, and failure capture — all automatic.
99
+
100
+ nest=True (default): if called inside another traced agent, this run
101
+ becomes a child trace (parent_trace_id) — required for multi-agent loops.
102
+
103
+ task_id: group retries of the same logical outcome for cost-per-task.
104
+ Pass cartha_task_id= at call time to override per-invocation.
105
+ """
106
+ team_id = team or os.getenv("CARTHA_TEAM_ID", "default_team")
107
+
108
+ def decorator(fn: Callable) -> Callable:
109
+ agent_key = id or fn.__name__
110
+ ops_decorator = ops.agent(
111
+ id=agent_key,
112
+ team=team_id,
113
+ org=org,
114
+ protocols=protocols,
115
+ description=description,
116
+ task_id=task_id,
117
+ nest=nest,
118
+ )
119
+
120
+ if asyncio.iscoroutinefunction(fn):
121
+ return ops_decorator(fn)
122
+
123
+ # Sync function: route it through the async instrumentation pipeline.
124
+ # The body runs in a worker thread so that sync helpers like
125
+ # remember_sync()/recall_sync() (which call asyncio.run internally)
126
+ # aren't executed inside this already-running event loop. to_thread
127
+ # copies contextvars, so the trace context follows into the thread.
128
+ async def _async_shim(*args: Any, **kwargs: Any) -> Any:
129
+ return await asyncio.to_thread(fn, *args, **kwargs)
130
+
131
+ _async_shim.__name__ = fn.__name__
132
+ _async_shim.__doc__ = fn.__doc__
133
+ instrumented = ops_decorator(_async_shim)
134
+
135
+ def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
136
+ return asyncio.run(instrumented(*args, **kwargs))
137
+
138
+ sync_wrapper.__name__ = fn.__name__
139
+ sync_wrapper.__doc__ = fn.__doc__
140
+ return sync_wrapper
141
+
142
+ return decorator
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: cartha-sdk
3
+ Version: 0.1.0
4
+ Summary: Cartha SDK — memory, traces, costs, and policies for AI agents
5
+ Author-email: Maulik Jadav <maulikjadav239@gmail.com>
6
+ Maintainer-email: Maulik Jadav <maulikjadav239@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://cartha.in
9
+ Project-URL: Documentation, https://cartha.in
10
+ Project-URL: Repository, https://github.com/maulik-jadav/nexus
11
+ Project-URL: Issues, https://github.com/maulik-jadav/nexus/issues
12
+ Project-URL: Source, https://github.com/maulik-jadav/nexus/tree/main/nexus/packages/sdk-python
13
+ Keywords: cartha,agents,llm,observability,tracing,memory,ai
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx>=0.27
27
+ Dynamic: license-file
28
+
29
+ # Cartha SDK (Python)
30
+
31
+ Instrument AI agents with memory, traces, costs, and policies on [Cartha](https://cartha.in).
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install cartha-sdk
37
+ ```
38
+
39
+ Requires Python 3.10+.
40
+
41
+ From source (development):
42
+
43
+ ```bash
44
+ pip install "git+https://github.com/maulik-jadav/nexus.git#subdirectory=nexus/packages/sdk-python"
45
+ # or from a local clone:
46
+ pip install -e nexus/packages/sdk-python
47
+ ```
48
+
49
+ ## Quickstart
50
+
51
+ ```bash
52
+ export CARTHA_API_KEY="cartha_..." # from the dashboard → Keys
53
+ export CARTHA_API_BASE="https://cartha.in" # your Cartha deployment
54
+ ```
55
+
56
+ ```python
57
+ import cartha
58
+
59
+ cartha.init() # picks up CARTHA_* env vars
60
+
61
+ @cartha.trace()
62
+ def run_agent(prompt: str):
63
+ return "..."
64
+ ```
65
+
66
+ `@cartha.trace()` works on sync and async functions. Every call registers the
67
+ agent, sends heartbeats, and records a full trace (start → steps → finish),
68
+ including failures.
69
+
70
+ ## Memory
71
+
72
+ ```python
73
+ import cartha
74
+
75
+ # async agents
76
+ await cartha.remember(user_id="u1", content="Prefers dark mode", scope="user")
77
+ hits = await cartha.recall(user_id="u1", context="UI preferences", scope=["user", "team"])
78
+
79
+ # sync code
80
+ cartha.remember_sync(user_id="u1", content="Prefers dark mode", scope="user")
81
+ ```
82
+
83
+ Scopes: `agent` (private) · `user` (all agents serving that user) ·
84
+ `team` (same `team_id`) · `org` (everyone in your org).
85
+
86
+ ## Nested agents (multi-agent loops)
87
+
88
+ By default, `@cartha.trace()` **auto-nests**: if a traced agent calls another
89
+ traced agent, the child run links via `parent_trace_id`. No env plumbing
90
+ required for in-process sub-agents.
91
+
92
+ ```python
93
+ @cartha.trace(id="parent")
94
+ async def orchestrator(user_id: str):
95
+ await cartha.ops.delegate(to_agent_id="worker", task_description="handle")
96
+ return await worker(user_id)
97
+
98
+ @cartha.trace(id="worker") # nests under orchestrator automatically
99
+ async def worker(user_id: str):
100
+ ...
101
+ ```
102
+
103
+ ## Cost per completed task
104
+
105
+ Share a `task_id` across retries so the dashboard rolls failed redoes into one outcome:
106
+
107
+ ```python
108
+ tid = cartha.task_context()
109
+ for attempt in range(3):
110
+ try:
111
+ await run_agent(..., cartha_task_id=tid)
112
+ break
113
+ except Exception:
114
+ continue
115
+ ```
116
+
117
+ ## Memory denial mode
118
+
119
+ Org setting (`PATCH /org` → `memory_denial_mode`):
120
+
121
+ - `denied_hint` (default): recall returns explicit denials without content so agents don't invent over a hole.
122
+ - `silent`: empty hits only (no existence leak).
123
+
124
+ ## Advanced
125
+
126
+ The full instrumentation API lives in `cartha.ops` (tool calls, cost events,
127
+ A2A delegation, policy checks, run nesting):
128
+
129
+ ```python
130
+ from cartha import ops
131
+ ```
132
+
133
+ **Legacy alias:** older code may `from nexus import ops`. That still works for
134
+ compatibility, but new code should use `cartha`.
135
+
136
+ **Trace diff:** `GET /api/v1/traces/diff?left=…&right=…` finds the first
137
+ diverging step between two runs (also on the dashboard).
138
+
139
+ ## Publishing (maintainers)
140
+
141
+ Releases are published from GitHub Actions when you push a tag matching
142
+ `sdk-python-v*` (for example `sdk-python-v0.1.0`).
143
+
144
+ Manual upload (emergency / first release):
145
+
146
+ ```bash
147
+ cd nexus/packages/sdk-python
148
+ python -m pip install --upgrade build twine
149
+ python -m build
150
+ # TestPyPI first (recommended):
151
+ python -m twine upload --repository testpypi dist/*
152
+ # Production PyPI:
153
+ python -m twine upload dist/*
154
+ ```
155
+
156
+ Use a PyPI API token (`pypi-...`), not your account password.
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ ./cartha/__init__.py
5
+ ./nexus/__init__.py
6
+ ./nexus/ops.py
7
+ cartha/__init__.py
8
+ cartha_sdk.egg-info/PKG-INFO
9
+ cartha_sdk.egg-info/SOURCES.txt
10
+ cartha_sdk.egg-info/dependency_links.txt
11
+ cartha_sdk.egg-info/requires.txt
12
+ cartha_sdk.egg-info/top_level.txt
13
+ nexus/__init__.py
14
+ nexus/ops.py
@@ -0,0 +1 @@
1
+ httpx>=0.27
@@ -0,0 +1,2 @@
1
+ cartha
2
+ nexus
@@ -0,0 +1,8 @@
1
+ """Legacy import path kept for backward compatibility.
2
+
3
+ Prefer ``import cartha`` / ``from cartha import ops`` in new code.
4
+ """
5
+
6
+ from . import ops
7
+
8
+ __all__ = ["ops"]