agentauthlayer 0.1.1__tar.gz → 0.1.3__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.
- agentauthlayer-0.1.3/PKG-INFO +221 -0
- agentauthlayer-0.1.3/README.md +201 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/__init__.py +12 -0
- agentauthlayer-0.1.3/agent_auth/__main__.py +5 -0
- agentauthlayer-0.1.3/agent_auth/cli.py +188 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/client.py +10 -2
- agentauthlayer-0.1.3/agent_auth/credentials.py +31 -0
- agentauthlayer-0.1.3/agent_auth/registry.py +61 -0
- agentauthlayer-0.1.3/agentauthlayer.egg-info/PKG-INFO +221 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agentauthlayer.egg-info/SOURCES.txt +2 -0
- agentauthlayer-0.1.3/agentauthlayer.egg-info/entry_points.txt +2 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/pyproject.toml +5 -3
- agentauthlayer-0.1.1/PKG-INFO +0 -111
- agentauthlayer-0.1.1/README.md +0 -90
- agentauthlayer-0.1.1/agent_auth/__main__.py +0 -4
- agentauthlayer-0.1.1/agent_auth/cli.py +0 -28
- agentauthlayer-0.1.1/agent_auth/registry.py +0 -90
- agentauthlayer-0.1.1/agentauthlayer.egg-info/PKG-INFO +0 -111
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/agents.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/audit.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/auth.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/context.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/core.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/delegation.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/exceptions.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/models.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/policy.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/policy_service.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/principals.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/session.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/storage.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/tokens.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agent_auth/users.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agentauthlayer.egg-info/dependency_links.txt +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agentauthlayer.egg-info/requires.txt +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/agentauthlayer.egg-info/top_level.txt +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/setup.cfg +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_agent_auth_library.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_auth_flow.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_core_first_boundary.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_health.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_iam_policy.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_project_flow.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_sqlite_repos.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_storage.py +0 -0
- {agentauthlayer-0.1.1 → agentauthlayer-0.1.3}/tests/test_tool_registry.py +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentauthlayer
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Library-first authentication and authorization SDK for AI agents
|
|
5
|
+
Author: Vaibhav Ahluwalia
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/agentauthlayer/
|
|
8
|
+
Keywords: agents,auth,authorization,iam,security,sdk
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Security
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.31.0
|
|
19
|
+
Requires-Dist: python-jose>=3.3.0
|
|
20
|
+
|
|
21
|
+
# agentauthlayer
|
|
22
|
+
|
|
23
|
+
Python SDK for integrating agent runtimes with the Agent Auth control plane.
|
|
24
|
+
|
|
25
|
+
`agentauthlayer` helps you:
|
|
26
|
+
- authenticate once and reuse local credentials
|
|
27
|
+
- register agents from code
|
|
28
|
+
- sync tool and capability definitions
|
|
29
|
+
- evaluate permissions against the control plane
|
|
30
|
+
- apply permission checks inside runtime functions
|
|
31
|
+
|
|
32
|
+
This package is the reusable SDK layer. It is intended for developers integrating Python agents, tools, and workflows with an Agent Auth deployment.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install agentauthlayer
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
### 1. First-time developer setup
|
|
43
|
+
|
|
44
|
+
For a fresh self-hosted deployment, complete the control plane setup before using `agentauth login`.
|
|
45
|
+
|
|
46
|
+
1. Start your Agent Auth deployment.
|
|
47
|
+
2. Open the UI in your browser.
|
|
48
|
+
3. Create the first super admin password.
|
|
49
|
+
4. Create your first project.
|
|
50
|
+
5. Then log in from the CLI.
|
|
51
|
+
|
|
52
|
+
Open the UI with:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
agentauth ui --base-url http://127.0.0.1:8002
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then log in once:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
agentauth login --base-url http://127.0.0.1:8002
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This stores local credentials so your code can connect without manually pasting a token every time.
|
|
65
|
+
|
|
66
|
+
Useful follow-up commands:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
agentauth whoami
|
|
70
|
+
agentauth logout
|
|
71
|
+
agentauth ui
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If the deployment has not been initialized yet, `agentauth login` will tell you to finish setup in the UI first.
|
|
75
|
+
|
|
76
|
+
### 2. Define tools and agents in code
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from agent_auth import register_tool, register_agent, require_permission
|
|
80
|
+
|
|
81
|
+
@register_tool(action="math.compute", description="Run approved math jobs")
|
|
82
|
+
@require_permission("math.compute", resource="math/basic")
|
|
83
|
+
def add(a: int, b: int, agent_id: str | None = None, role: str | None = None, context: dict | None = None):
|
|
84
|
+
return a + b
|
|
85
|
+
|
|
86
|
+
register_agent(
|
|
87
|
+
agent_id="math-agent",
|
|
88
|
+
name="Math Agent",
|
|
89
|
+
owner="you@company.com",
|
|
90
|
+
role="research_agent",
|
|
91
|
+
project_id="ai-platform",
|
|
92
|
+
scopes=[],
|
|
93
|
+
)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Sync everything with one command
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
agentauth sync --module your_module_name
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This imports the module, discovers registered tools and agents, syncs capability definitions, and creates agents through the control plane.
|
|
103
|
+
|
|
104
|
+
## SDK client usage
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from agent_auth import AuthAPIClient
|
|
108
|
+
|
|
109
|
+
client = AuthAPIClient()
|
|
110
|
+
|
|
111
|
+
agent = client.create_agent(
|
|
112
|
+
agent_id="research-bot-01",
|
|
113
|
+
name="Research Bot 01",
|
|
114
|
+
owner="vaibhav@company.com",
|
|
115
|
+
role="research_agent",
|
|
116
|
+
scopes=[],
|
|
117
|
+
project_id="ai-platform",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
print(agent)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Environment variables
|
|
124
|
+
|
|
125
|
+
If you prefer non-interactive configuration, the SDK also supports environment variables:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
export AGENT_AUTH_URL=http://127.0.0.1:8002
|
|
129
|
+
export AGENT_AUTH_TOKEN=YOUR_ADMIN_OR_SERVICE_TOKEN
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`AGENT_AUTH_TOKEN` is typically a bearer token, often represented as a long JWT string.
|
|
133
|
+
|
|
134
|
+
Recommended usage:
|
|
135
|
+
- use `agentauth login` for local human developer workflows
|
|
136
|
+
- use `AGENT_AUTH_TOKEN` for CI, automation, or service-driven execution
|
|
137
|
+
|
|
138
|
+
If an env token expires, requests will fail until you replace it or log in again.
|
|
139
|
+
Avoid committing tokens into source control or long-lived shared `.env` files.
|
|
140
|
+
|
|
141
|
+
Resolution order used by `AuthAPIClient()`:
|
|
142
|
+
1. explicit constructor arguments
|
|
143
|
+
2. environment variables
|
|
144
|
+
3. stored local credentials from `agentauth login`
|
|
145
|
+
|
|
146
|
+
## Common tasks
|
|
147
|
+
|
|
148
|
+
### Sync tools manually
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
client.sync_tools([
|
|
152
|
+
{"action": "tool.search_web", "description": "Search the web"},
|
|
153
|
+
{"action": "docs.read", "description": "Read protected docs"},
|
|
154
|
+
])
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Evaluate access
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
decision = client.evaluate(
|
|
161
|
+
principal_id="research-bot-01",
|
|
162
|
+
action="tool.search_web",
|
|
163
|
+
resource="web/*",
|
|
164
|
+
role="research_agent",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
print(decision)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Fetch or delete an agent
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
agent = client.get_agent("research-bot-01")
|
|
174
|
+
print(agent)
|
|
175
|
+
|
|
176
|
+
result = client.delete_agent("research-bot-01")
|
|
177
|
+
print(result)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
CLI equivalent:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
agentauth delete-agent research-bot-01
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Public package scope
|
|
187
|
+
|
|
188
|
+
This package provides:
|
|
189
|
+
- the Python SDK (`agent_auth`)
|
|
190
|
+
- CLI helpers for login, sync, and agent cleanup
|
|
191
|
+
- registry-based tool and agent sync
|
|
192
|
+
- permission evaluation helpers
|
|
193
|
+
|
|
194
|
+
It does not package the full control plane server or admin dashboard.
|
|
195
|
+
|
|
196
|
+
## Suitable use cases
|
|
197
|
+
|
|
198
|
+
- Python agent runtimes
|
|
199
|
+
- tool-based workflows
|
|
200
|
+
- service-to-control-plane integrations
|
|
201
|
+
- local development with stored credentials
|
|
202
|
+
- CI or automation using environment variables
|
|
203
|
+
|
|
204
|
+
## Requirements
|
|
205
|
+
|
|
206
|
+
- Python 3.10+
|
|
207
|
+
- access to a running Agent Auth control plane
|
|
208
|
+
|
|
209
|
+
## Notes
|
|
210
|
+
|
|
211
|
+
The import path remains:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from agent_auth import ...
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
while the published package name is:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
pip install agentauthlayer
|
|
221
|
+
```
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# agentauthlayer
|
|
2
|
+
|
|
3
|
+
Python SDK for integrating agent runtimes with the Agent Auth control plane.
|
|
4
|
+
|
|
5
|
+
`agentauthlayer` helps you:
|
|
6
|
+
- authenticate once and reuse local credentials
|
|
7
|
+
- register agents from code
|
|
8
|
+
- sync tool and capability definitions
|
|
9
|
+
- evaluate permissions against the control plane
|
|
10
|
+
- apply permission checks inside runtime functions
|
|
11
|
+
|
|
12
|
+
This package is the reusable SDK layer. It is intended for developers integrating Python agents, tools, and workflows with an Agent Auth deployment.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install agentauthlayer
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quickstart
|
|
21
|
+
|
|
22
|
+
### 1. First-time developer setup
|
|
23
|
+
|
|
24
|
+
For a fresh self-hosted deployment, complete the control plane setup before using `agentauth login`.
|
|
25
|
+
|
|
26
|
+
1. Start your Agent Auth deployment.
|
|
27
|
+
2. Open the UI in your browser.
|
|
28
|
+
3. Create the first super admin password.
|
|
29
|
+
4. Create your first project.
|
|
30
|
+
5. Then log in from the CLI.
|
|
31
|
+
|
|
32
|
+
Open the UI with:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
agentauth ui --base-url http://127.0.0.1:8002
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then log in once:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
agentauth login --base-url http://127.0.0.1:8002
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This stores local credentials so your code can connect without manually pasting a token every time.
|
|
45
|
+
|
|
46
|
+
Useful follow-up commands:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
agentauth whoami
|
|
50
|
+
agentauth logout
|
|
51
|
+
agentauth ui
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If the deployment has not been initialized yet, `agentauth login` will tell you to finish setup in the UI first.
|
|
55
|
+
|
|
56
|
+
### 2. Define tools and agents in code
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from agent_auth import register_tool, register_agent, require_permission
|
|
60
|
+
|
|
61
|
+
@register_tool(action="math.compute", description="Run approved math jobs")
|
|
62
|
+
@require_permission("math.compute", resource="math/basic")
|
|
63
|
+
def add(a: int, b: int, agent_id: str | None = None, role: str | None = None, context: dict | None = None):
|
|
64
|
+
return a + b
|
|
65
|
+
|
|
66
|
+
register_agent(
|
|
67
|
+
agent_id="math-agent",
|
|
68
|
+
name="Math Agent",
|
|
69
|
+
owner="you@company.com",
|
|
70
|
+
role="research_agent",
|
|
71
|
+
project_id="ai-platform",
|
|
72
|
+
scopes=[],
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Sync everything with one command
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
agentauth sync --module your_module_name
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This imports the module, discovers registered tools and agents, syncs capability definitions, and creates agents through the control plane.
|
|
83
|
+
|
|
84
|
+
## SDK client usage
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from agent_auth import AuthAPIClient
|
|
88
|
+
|
|
89
|
+
client = AuthAPIClient()
|
|
90
|
+
|
|
91
|
+
agent = client.create_agent(
|
|
92
|
+
agent_id="research-bot-01",
|
|
93
|
+
name="Research Bot 01",
|
|
94
|
+
owner="vaibhav@company.com",
|
|
95
|
+
role="research_agent",
|
|
96
|
+
scopes=[],
|
|
97
|
+
project_id="ai-platform",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
print(agent)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Environment variables
|
|
104
|
+
|
|
105
|
+
If you prefer non-interactive configuration, the SDK also supports environment variables:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
export AGENT_AUTH_URL=http://127.0.0.1:8002
|
|
109
|
+
export AGENT_AUTH_TOKEN=YOUR_ADMIN_OR_SERVICE_TOKEN
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`AGENT_AUTH_TOKEN` is typically a bearer token, often represented as a long JWT string.
|
|
113
|
+
|
|
114
|
+
Recommended usage:
|
|
115
|
+
- use `agentauth login` for local human developer workflows
|
|
116
|
+
- use `AGENT_AUTH_TOKEN` for CI, automation, or service-driven execution
|
|
117
|
+
|
|
118
|
+
If an env token expires, requests will fail until you replace it or log in again.
|
|
119
|
+
Avoid committing tokens into source control or long-lived shared `.env` files.
|
|
120
|
+
|
|
121
|
+
Resolution order used by `AuthAPIClient()`:
|
|
122
|
+
1. explicit constructor arguments
|
|
123
|
+
2. environment variables
|
|
124
|
+
3. stored local credentials from `agentauth login`
|
|
125
|
+
|
|
126
|
+
## Common tasks
|
|
127
|
+
|
|
128
|
+
### Sync tools manually
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
client.sync_tools([
|
|
132
|
+
{"action": "tool.search_web", "description": "Search the web"},
|
|
133
|
+
{"action": "docs.read", "description": "Read protected docs"},
|
|
134
|
+
])
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Evaluate access
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
decision = client.evaluate(
|
|
141
|
+
principal_id="research-bot-01",
|
|
142
|
+
action="tool.search_web",
|
|
143
|
+
resource="web/*",
|
|
144
|
+
role="research_agent",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
print(decision)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Fetch or delete an agent
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
agent = client.get_agent("research-bot-01")
|
|
154
|
+
print(agent)
|
|
155
|
+
|
|
156
|
+
result = client.delete_agent("research-bot-01")
|
|
157
|
+
print(result)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
CLI equivalent:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
agentauth delete-agent research-bot-01
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Public package scope
|
|
167
|
+
|
|
168
|
+
This package provides:
|
|
169
|
+
- the Python SDK (`agent_auth`)
|
|
170
|
+
- CLI helpers for login, sync, and agent cleanup
|
|
171
|
+
- registry-based tool and agent sync
|
|
172
|
+
- permission evaluation helpers
|
|
173
|
+
|
|
174
|
+
It does not package the full control plane server or admin dashboard.
|
|
175
|
+
|
|
176
|
+
## Suitable use cases
|
|
177
|
+
|
|
178
|
+
- Python agent runtimes
|
|
179
|
+
- tool-based workflows
|
|
180
|
+
- service-to-control-plane integrations
|
|
181
|
+
- local development with stored credentials
|
|
182
|
+
- CI or automation using environment variables
|
|
183
|
+
|
|
184
|
+
## Requirements
|
|
185
|
+
|
|
186
|
+
- Python 3.10+
|
|
187
|
+
- access to a running Agent Auth control plane
|
|
188
|
+
|
|
189
|
+
## Notes
|
|
190
|
+
|
|
191
|
+
The import path remains:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from agent_auth import ...
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
while the published package name is:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pip install agentauthlayer
|
|
201
|
+
```
|
|
@@ -15,6 +15,13 @@ from agent_auth.exceptions import (
|
|
|
15
15
|
from agent_auth.models import Agent, TokenClaims, TokenRecord, User, UserClaims
|
|
16
16
|
from agent_auth.policy import PolicyDecision, PolicyEvaluator, PolicyRequest, PolicyStatement, RoleDefinition, require_permission
|
|
17
17
|
from agent_auth.principals import AgentPrincipal, Principal, SystemPrincipal, UserPrincipal, user_scopes_for_role
|
|
18
|
+
from agent_auth.registry import (
|
|
19
|
+
clear_registries,
|
|
20
|
+
list_registered_agents,
|
|
21
|
+
list_registered_tools,
|
|
22
|
+
register_agent,
|
|
23
|
+
register_tool,
|
|
24
|
+
)
|
|
18
25
|
|
|
19
26
|
__all__ = [
|
|
20
27
|
"Agent",
|
|
@@ -40,9 +47,14 @@ __all__ = [
|
|
|
40
47
|
"User",
|
|
41
48
|
"UserClaims",
|
|
42
49
|
"UserPrincipal",
|
|
50
|
+
"clear_registries",
|
|
51
|
+
"list_registered_agents",
|
|
52
|
+
"list_registered_tools",
|
|
43
53
|
"principal_fields",
|
|
44
54
|
"principal_from_agent",
|
|
45
55
|
"principal_from_user",
|
|
56
|
+
"register_agent",
|
|
57
|
+
"register_tool",
|
|
46
58
|
"require_permission",
|
|
47
59
|
"user_scopes_for_role",
|
|
48
60
|
]
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import getpass
|
|
5
|
+
import importlib
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
import webbrowser
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
|
|
12
|
+
from agent_auth.client import AuthAPIClient
|
|
13
|
+
from agent_auth.credentials import clear_credentials, load_credentials, save_credentials
|
|
14
|
+
from agent_auth.registry import clear_registries, list_registered_agents, list_registered_tools
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _response_detail(response: requests.Response) -> str:
|
|
18
|
+
try:
|
|
19
|
+
payload = response.json()
|
|
20
|
+
if isinstance(payload, dict) and payload.get('detail'):
|
|
21
|
+
return str(payload['detail'])
|
|
22
|
+
except Exception:
|
|
23
|
+
pass
|
|
24
|
+
return response.text.strip() or f'Request failed with status {response.status_code}'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _bootstrap_status(base_url: str) -> bool | None:
|
|
28
|
+
try:
|
|
29
|
+
response = requests.get(f"{base_url}/bootstrap/status", timeout=10)
|
|
30
|
+
except requests.RequestException:
|
|
31
|
+
return None
|
|
32
|
+
if not response.ok:
|
|
33
|
+
return None
|
|
34
|
+
try:
|
|
35
|
+
payload = response.json()
|
|
36
|
+
return bool(payload.get('is_setup'))
|
|
37
|
+
except Exception:
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def login_command(args) -> int:
|
|
42
|
+
base_url = (args.base_url or 'http://127.0.0.1:8002').rstrip('/')
|
|
43
|
+
setup_status = _bootstrap_status(base_url)
|
|
44
|
+
|
|
45
|
+
if setup_status is False:
|
|
46
|
+
print(
|
|
47
|
+
'\nThis Agent Auth deployment has not been initialized yet.\n'
|
|
48
|
+
'First-time developer setup:\n'
|
|
49
|
+
f' 1. Open the UI: {base_url}\n'
|
|
50
|
+
' 2. Create the first super admin password\n'
|
|
51
|
+
' 3. Create your first project\n'
|
|
52
|
+
' 4. Run agentauth login again\n',
|
|
53
|
+
file=sys.stderr,
|
|
54
|
+
)
|
|
55
|
+
return 1
|
|
56
|
+
|
|
57
|
+
email = args.email or input('Email: ').strip()
|
|
58
|
+
password = args.password or getpass.getpass('Password: ')
|
|
59
|
+
|
|
60
|
+
response = requests.post(
|
|
61
|
+
f"{base_url}/users/login",
|
|
62
|
+
json={"email": email, "password": password},
|
|
63
|
+
timeout=30,
|
|
64
|
+
)
|
|
65
|
+
if not response.ok:
|
|
66
|
+
detail = _response_detail(response)
|
|
67
|
+
if response.status_code == 401 and setup_status is not True:
|
|
68
|
+
print(
|
|
69
|
+
f"{detail}\n\n"
|
|
70
|
+
'If this is your first time using this deployment, initialize it first in the UI, then try logging in again.',
|
|
71
|
+
file=sys.stderr,
|
|
72
|
+
)
|
|
73
|
+
else:
|
|
74
|
+
print(detail, file=sys.stderr)
|
|
75
|
+
return 1
|
|
76
|
+
|
|
77
|
+
payload = response.json()
|
|
78
|
+
save_credentials({
|
|
79
|
+
'base_url': base_url,
|
|
80
|
+
'token': payload['access_token'],
|
|
81
|
+
'email': payload['user']['email'],
|
|
82
|
+
})
|
|
83
|
+
print(f"Logged in to {base_url} as {payload['user']['email']}")
|
|
84
|
+
return 0
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def whoami_command(args) -> int:
|
|
88
|
+
creds = load_credentials()
|
|
89
|
+
if not creds:
|
|
90
|
+
print('Not logged in.')
|
|
91
|
+
return 1
|
|
92
|
+
client = AuthAPIClient()
|
|
93
|
+
me = client.me()
|
|
94
|
+
print(json.dumps(me, indent=2))
|
|
95
|
+
return 0
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def logout_command(args) -> int:
|
|
99
|
+
clear_credentials()
|
|
100
|
+
print('Logged out.')
|
|
101
|
+
return 0
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def sync_command(args) -> int:
|
|
105
|
+
clear_registries()
|
|
106
|
+
importlib.import_module(args.module)
|
|
107
|
+
|
|
108
|
+
client = AuthAPIClient()
|
|
109
|
+
tools = list_registered_tools()
|
|
110
|
+
agents = list_registered_agents()
|
|
111
|
+
|
|
112
|
+
if tools:
|
|
113
|
+
client.sync_tools([
|
|
114
|
+
{'action': tool.action, 'description': tool.description}
|
|
115
|
+
for tool in tools
|
|
116
|
+
])
|
|
117
|
+
|
|
118
|
+
created_agents = []
|
|
119
|
+
for agent in agents:
|
|
120
|
+
created_agents.append(client.create_agent(
|
|
121
|
+
agent_id=agent.agent_id,
|
|
122
|
+
name=agent.name,
|
|
123
|
+
owner=agent.owner,
|
|
124
|
+
role=agent.role,
|
|
125
|
+
scopes=agent.scopes,
|
|
126
|
+
project_id=agent.project_id,
|
|
127
|
+
))
|
|
128
|
+
|
|
129
|
+
print(json.dumps({
|
|
130
|
+
'module': args.module,
|
|
131
|
+
'synced_tools': [tool.action for tool in tools],
|
|
132
|
+
'synced_agents': [agent['agent_id'] for agent in created_agents],
|
|
133
|
+
}, indent=2))
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def delete_agent_command(args) -> int:
|
|
138
|
+
client = AuthAPIClient()
|
|
139
|
+
result = client.delete_agent(args.agent_id)
|
|
140
|
+
print(json.dumps(result, indent=2))
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def ui_command(args) -> int:
|
|
145
|
+
creds = load_credentials() or {}
|
|
146
|
+
base_url = (args.base_url or creds.get('base_url') or 'http://127.0.0.1:8002').rstrip('/')
|
|
147
|
+
webbrowser.open(base_url)
|
|
148
|
+
print(f'Opened UI: {base_url}')
|
|
149
|
+
return 0
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def main():
|
|
153
|
+
parser = argparse.ArgumentParser(prog='agentauth', description='Agent Auth SDK CLI')
|
|
154
|
+
subparsers = parser.add_subparsers(dest='command')
|
|
155
|
+
|
|
156
|
+
login_parser = subparsers.add_parser('login', help='Log in and store local credentials')
|
|
157
|
+
login_parser.add_argument('--base-url', default='http://127.0.0.1:8002')
|
|
158
|
+
login_parser.add_argument('--email')
|
|
159
|
+
login_parser.add_argument('--password')
|
|
160
|
+
login_parser.set_defaults(func=login_command)
|
|
161
|
+
|
|
162
|
+
whoami_parser = subparsers.add_parser('whoami', help='Show the currently stored user context')
|
|
163
|
+
whoami_parser.set_defaults(func=whoami_command)
|
|
164
|
+
|
|
165
|
+
logout_parser = subparsers.add_parser('logout', help='Clear stored local credentials')
|
|
166
|
+
logout_parser.set_defaults(func=logout_command)
|
|
167
|
+
|
|
168
|
+
sync_parser = subparsers.add_parser('sync', help='Import a module and sync its registered tools and agents')
|
|
169
|
+
sync_parser.add_argument('--module', required=True)
|
|
170
|
+
sync_parser.set_defaults(func=sync_command)
|
|
171
|
+
|
|
172
|
+
delete_agent_parser = subparsers.add_parser('delete-agent', help='Delete an agent by ID')
|
|
173
|
+
delete_agent_parser.add_argument('agent_id')
|
|
174
|
+
delete_agent_parser.set_defaults(func=delete_agent_command)
|
|
175
|
+
|
|
176
|
+
ui_parser = subparsers.add_parser('ui', help='Open the configured control plane UI in a browser')
|
|
177
|
+
ui_parser.add_argument('--base-url')
|
|
178
|
+
ui_parser.set_defaults(func=ui_command)
|
|
179
|
+
|
|
180
|
+
args = parser.parse_args()
|
|
181
|
+
if not hasattr(args, 'func'):
|
|
182
|
+
parser.print_help()
|
|
183
|
+
return 1
|
|
184
|
+
return args.func(args)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if __name__ == '__main__':
|
|
188
|
+
raise SystemExit(main())
|
|
@@ -6,6 +6,7 @@ from typing import Any
|
|
|
6
6
|
import requests
|
|
7
7
|
|
|
8
8
|
from agent_auth.context import AuthContext
|
|
9
|
+
from agent_auth.credentials import load_credentials
|
|
9
10
|
from agent_auth.exceptions import (
|
|
10
11
|
AgentNotFoundError,
|
|
11
12
|
AuthServiceError,
|
|
@@ -19,8 +20,9 @@ class AuthAPIClient:
|
|
|
19
20
|
"""Thin SDK client for talking to the Agent Auth control plane."""
|
|
20
21
|
|
|
21
22
|
def __init__(self, base_url: str | None = None, token: str | None = None, timeout: int = 30) -> None:
|
|
22
|
-
|
|
23
|
-
self.
|
|
23
|
+
stored = load_credentials() or {}
|
|
24
|
+
self.base_url = (base_url or os.getenv("AGENT_AUTH_URL") or stored.get("base_url") or "http://127.0.0.1:8002").rstrip("/")
|
|
25
|
+
self.token = token or os.getenv("AGENT_AUTH_TOKEN") or stored.get("token")
|
|
24
26
|
self.timeout = timeout
|
|
25
27
|
|
|
26
28
|
def _headers(self) -> dict[str, str]:
|
|
@@ -62,6 +64,9 @@ class AuthAPIClient:
|
|
|
62
64
|
def health(self) -> dict[str, Any]:
|
|
63
65
|
return self._request("GET", "/health")
|
|
64
66
|
|
|
67
|
+
def me(self) -> dict[str, Any]:
|
|
68
|
+
return self._request("GET", "/users/me")
|
|
69
|
+
|
|
65
70
|
def create_agent(self, agent_id: str, name: str, owner: str, role: str, scopes: list[str], project_id: str | None = None) -> dict[str, Any]:
|
|
66
71
|
payload = {
|
|
67
72
|
"agent_id": agent_id,
|
|
@@ -74,6 +79,9 @@ class AuthAPIClient:
|
|
|
74
79
|
payload["project_id"] = project_id
|
|
75
80
|
return self._request("POST", "/agents", json=payload)
|
|
76
81
|
|
|
82
|
+
def delete_agent(self, agent_id: str) -> dict[str, Any]:
|
|
83
|
+
return self._request("DELETE", f"/agents/{agent_id}")
|
|
84
|
+
|
|
77
85
|
def get_agent(self, agent_id: str) -> dict[str, Any]:
|
|
78
86
|
return self._request("GET", f"/agents/{agent_id}")
|
|
79
87
|
|