greennode-agentbase 1.0.1__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.
Files changed (46) hide show
  1. greennode_agentbase-1.0.1/.github/workflows/publish.yml +272 -0
  2. greennode_agentbase-1.0.1/.gitignore +3 -0
  3. greennode_agentbase-1.0.1/PKG-INFO +367 -0
  4. greennode_agentbase-1.0.1/README.md +333 -0
  5. greennode_agentbase-1.0.1/pyproject.toml +138 -0
  6. greennode_agentbase-1.0.1/setup.py +42 -0
  7. greennode_agentbase-1.0.1/src/greennode_agentbase/__init__.py +78 -0
  8. greennode_agentbase-1.0.1/src/greennode_agentbase/cli/__init__.py +6 -0
  9. greennode_agentbase-1.0.1/src/greennode_agentbase/cli/deploy.py +756 -0
  10. greennode_agentbase-1.0.1/src/greennode_agentbase/cli/main.py +84 -0
  11. greennode_agentbase-1.0.1/src/greennode_agentbase/cli/memory.py +681 -0
  12. greennode_agentbase-1.0.1/src/greennode_agentbase/cli/runtime.py +301 -0
  13. greennode_agentbase-1.0.1/src/greennode_agentbase/core/__init__.py +8 -0
  14. greennode_agentbase-1.0.1/src/greennode_agentbase/core/authenticated_client.py +215 -0
  15. greennode_agentbase-1.0.1/src/greennode_agentbase/core/base.py +104 -0
  16. greennode_agentbase-1.0.1/src/greennode_agentbase/core/engine.py +5 -0
  17. greennode_agentbase-1.0.1/src/greennode_agentbase/core/engine.pyx +7 -0
  18. greennode_agentbase-1.0.1/src/greennode_agentbase/core/http_client.py +299 -0
  19. greennode_agentbase-1.0.1/src/greennode_agentbase/core/loader.py +79 -0
  20. greennode_agentbase-1.0.1/src/greennode_agentbase/core/logging.py +237 -0
  21. greennode_agentbase-1.0.1/src/greennode_agentbase/core/method_generator.py +261 -0
  22. greennode_agentbase-1.0.1/src/greennode_agentbase/exceptions.py +155 -0
  23. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/__init__.py +63 -0
  24. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/auth.py +753 -0
  25. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/client.py +198 -0
  26. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/config.py +132 -0
  27. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/credentials.py +130 -0
  28. greennode_agentbase-1.0.1/src/greennode_agentbase/identity/models.py +332 -0
  29. greennode_agentbase-1.0.1/src/greennode_agentbase/memory/__init__.py +44 -0
  30. greennode_agentbase-1.0.1/src/greennode_agentbase/memory/client.py +50 -0
  31. greennode_agentbase-1.0.1/src/greennode_agentbase/memory/models.py +166 -0
  32. greennode_agentbase-1.0.1/src/greennode_agentbase/py.typed +0 -0
  33. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/__init__.py +18 -0
  34. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/app.py +1051 -0
  35. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/client.py +57 -0
  36. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/config.py +215 -0
  37. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/context.py +215 -0
  38. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/models.py +238 -0
  39. greennode_agentbase-1.0.1/src/greennode_agentbase/runtime/utils.py +82 -0
  40. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/__init__.py +2 -0
  41. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/identity/__init__.py +2 -0
  42. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/identity/api.json.gz +0 -0
  43. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/memory/__init__.py +1 -0
  44. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/memory/api.json.gz +0 -0
  45. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/runtime/__init__.py +1 -0
  46. greennode_agentbase-1.0.1/src/greennode_agentbase/specs/runtime/api.json.gz +0 -0
@@ -0,0 +1,272 @@
1
+ name: Publish Package
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - dev
7
+ tags:
8
+ - 'v*'
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ publish-dev:
13
+ name: Publish Dev Version to TestPyPI
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+ if: github.ref == 'refs/heads/dev' && github.event_name == 'push'
19
+ environment:
20
+ name: testpypi
21
+
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Set up Python
27
+ uses: actions/setup-python@v5
28
+ with:
29
+ python-version: '3.11'
30
+
31
+ - name: Install hatch
32
+ run: pip install hatch
33
+
34
+ - name: Inject Multiple Configs
35
+ env:
36
+ IDENTITY_CONFIG: ${{ secrets.IDENTITY_CONFIG }}
37
+ RUNTIME_CONFIG: ${{ secrets.RUNTIME_CONFIG }}
38
+ MEMORY_CONFIG: ${{ secrets.MEMORY_CONFIG }}
39
+ run: |
40
+ echo -n "$IDENTITY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/identity/api.json.gz
41
+ echo -n "$RUNTIME_CONFIG" | base64 --decode > src/greennode_agentbase/specs/runtime/api.json.gz
42
+ echo -n "$MEMORY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/memory/api.json.gz
43
+
44
+ - name: Verify Files Exist
45
+ run: |
46
+ ls -l src/greennode_agentbase/specs/identity/api.json.gz
47
+ ls -l src/greennode_agentbase/specs/runtime/api.json.gz
48
+ ls -l src/greennode_agentbase/specs/memory/api.json.gz
49
+
50
+ if [ ! -s src/greennode_agentbase/specs/identity/api.json.gz ]; then
51
+ echo "Error: Identity config is empty!"
52
+ exit 1
53
+ fi
54
+
55
+ - name: Extract base version from pyproject.toml
56
+ id: get_version
57
+ run: |
58
+ python << PYTHON_SCRIPT
59
+ import os
60
+ import sys
61
+ try:
62
+ import tomllib
63
+ with open('pyproject.toml', 'rb') as f:
64
+ data = tomllib.load(f)
65
+ version = data['project']['version']
66
+ except ImportError:
67
+ import tomli
68
+ with open('pyproject.toml', 'rb') as f:
69
+ data = tomli.load(f)
70
+ version = data['project']['version']
71
+ output_file = os.environ['GITHUB_OUTPUT']
72
+ with open(output_file, 'a') as f:
73
+ f.write(f'base_version={version}\n')
74
+ PYTHON_SCRIPT
75
+
76
+ - name: Generate dev version
77
+ id: dev_version
78
+ run: |
79
+ TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
80
+ DEV_VERSION="${{ steps.get_version.outputs.base_version }}dev-$TIMESTAMP"
81
+ echo "version=$DEV_VERSION" >> $GITHUB_OUTPUT
82
+ echo "Generated dev version: $DEV_VERSION"
83
+
84
+ - name: Update pyproject.toml with dev version
85
+ run: |
86
+ python << EOF
87
+ import re
88
+ with open('pyproject.toml', 'r') as f:
89
+ content = f.read()
90
+ content = re.sub(
91
+ r'^version = ".*"',
92
+ f'version = "${{ steps.dev_version.outputs.version }}"',
93
+ content,
94
+ flags=re.MULTILINE
95
+ )
96
+ with open('pyproject.toml', 'w') as f:
97
+ f.write(content)
98
+ EOF
99
+
100
+ - name: Build package
101
+ run: hatch build
102
+
103
+ - name: Publish to TestPyPI
104
+ uses: pypa/gh-action-pypi-publish@release/v1
105
+ with:
106
+ packages-dir: dist/
107
+ repository-url: https://test.pypi.org/legacy/
108
+
109
+ test-publish:
110
+ name: Verify on TestPyPI
111
+ runs-on: ubuntu-latest
112
+ environment: testpypi
113
+ permissions:
114
+ id-token: write
115
+ contents: read
116
+ if: startsWith(github.ref, 'refs/tags/v')
117
+ steps:
118
+ - name: Checkout code
119
+ uses: actions/checkout@v4
120
+
121
+ - name: Set up Python
122
+ uses: actions/setup-python@v5
123
+ with:
124
+ python-version: '3.11'
125
+
126
+ - name: Install hatch
127
+ run: pip install hatch
128
+
129
+ - name: Inject Multiple Configs
130
+ env:
131
+ IDENTITY_CONFIG: ${{ secrets.IDENTITY_CONFIG }}
132
+ RUNTIME_CONFIG: ${{ secrets.RUNTIME_CONFIG }}
133
+ MEMORY_CONFIG: ${{ secrets.MEMORY_CONFIG }}
134
+ run: |
135
+ echo -n "$IDENTITY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/identity/api.json.gz
136
+ echo -n "$RUNTIME_CONFIG" | base64 --decode > src/greennode_agentbase/specs/runtime/api.json.gz
137
+ echo -n "$MEMORY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/memory/api.json.gz
138
+
139
+ - name: Verify Files Exist
140
+ run: |
141
+ ls -l src/greennode_agentbase/specs/identity/api.json.gz
142
+ ls -l src/greennode_agentbase/specs/runtime/api.json.gz
143
+ ls -l src/greennode_agentbase/specs/memory/api.json.gz
144
+
145
+ if [ ! -s src/greennode_agentbase/specs/identity/api.json.gz ]; then
146
+ echo "Error: Identity config is empty!"
147
+ exit 1
148
+ fi
149
+
150
+ - name: Extract version from tag
151
+ id: get_tag_version
152
+ run: |
153
+ if [[ "${{ github.ref }}" =~ ^refs/tags/v(.+)$ ]]; then
154
+ TAG_VERSION="${BASH_REMATCH[1]}"
155
+ else
156
+ TAG_VERSION="${GITHUB_REF#refs/tags/v}"
157
+ fi
158
+ echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT
159
+ echo "Extracted version from tag: $TAG_VERSION"
160
+
161
+ - name: Update pyproject.toml with tag version
162
+ run: |
163
+ python << EOF
164
+ import re
165
+ with open('pyproject.toml', 'r') as f:
166
+ content = f.read()
167
+ content = re.sub(
168
+ r'^version = ".*"',
169
+ f'version = "${{ steps.get_tag_version.outputs.version }}"',
170
+ content,
171
+ flags=re.MULTILINE
172
+ )
173
+ with open('pyproject.toml', 'w') as f:
174
+ f.write(content)
175
+ EOF
176
+
177
+ - name: Build package
178
+ run: hatch build
179
+
180
+ - name: Verify Package Contents (Crucial)
181
+ run: |
182
+ echo "Checking for json.gz in the built wheel..."
183
+ unzip -l dist/*.whl | grep "json.gz"
184
+ - name: Publish to TestPyPI
185
+ uses: pypa/gh-action-pypi-publish@release/v1
186
+ with:
187
+ repository-url: https://test.pypi.org/legacy/
188
+
189
+ publish-release:
190
+ name: Publish Release to PyPI
191
+ needs: test-publish
192
+ runs-on: ubuntu-latest
193
+ permissions:
194
+ id-token: write
195
+ contents: read
196
+ if: startsWith(github.ref, 'refs/tags/v')
197
+ environment:
198
+ name: pypi
199
+
200
+ steps:
201
+ - name: Checkout code
202
+ uses: actions/checkout@v4
203
+
204
+ - name: Set up Python
205
+ uses: actions/setup-python@v5
206
+ with:
207
+ python-version: '3.11'
208
+
209
+ - name: Install hatch
210
+ run: pip install hatch
211
+
212
+ - name: Inject Multiple Configs
213
+ env:
214
+ IDENTITY_CONFIG: ${{ secrets.IDENTITY_CONFIG }}
215
+ RUNTIME_CONFIG: ${{ secrets.RUNTIME_CONFIG }}
216
+ MEMORY_CONFIG: ${{ secrets.MEMORY_CONFIG }}
217
+ run: |
218
+ echo -n "$IDENTITY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/identity/api.json.gz
219
+ echo -n "$RUNTIME_CONFIG" | base64 --decode > src/greennode_agentbase/specs/runtime/api.json.gz
220
+ echo -n "$MEMORY_CONFIG" | base64 --decode > src/greennode_agentbase/specs/memory/api.json.gz
221
+
222
+ - name: Verify Files Exist
223
+ run: |
224
+ ls -l src/greennode_agentbase/specs/identity/api.json.gz
225
+ ls -l src/greennode_agentbase/specs/runtime/api.json.gz
226
+ ls -l src/greennode_agentbase/specs/memory/api.json.gz
227
+
228
+ if [ ! -s src/greennode_agentbase/specs/identity/api.json.gz ]; then
229
+ echo "Error: Identity config is empty!"
230
+ exit 1
231
+ fi
232
+
233
+ - name: Extract version from tag
234
+ id: get_tag_version
235
+ run: |
236
+ if [[ "${{ github.ref }}" =~ ^refs/tags/v(.+)$ ]]; then
237
+ TAG_VERSION="${BASH_REMATCH[1]}"
238
+ else
239
+ TAG_VERSION="${GITHUB_REF#refs/tags/v}"
240
+ fi
241
+ echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT
242
+ echo "Extracted version from tag: $TAG_VERSION"
243
+
244
+ - name: Update pyproject.toml with tag version
245
+ run: |
246
+ python << EOF
247
+ import re
248
+ with open('pyproject.toml', 'r') as f:
249
+ content = f.read()
250
+ content = re.sub(
251
+ r'^version = ".*"',
252
+ f'version = "${{ steps.get_tag_version.outputs.version }}"',
253
+ content,
254
+ flags=re.MULTILINE
255
+ )
256
+ with open('pyproject.toml', 'w') as f:
257
+ f.write(content)
258
+ EOF
259
+
260
+ - name: Build package
261
+ run: hatch build
262
+
263
+ - name: Verify Package Contents (Crucial)
264
+ run: |
265
+ echo "Checking for json.gz in the built wheel..."
266
+ unzip -l dist/*.whl | grep "json.gz"
267
+
268
+ - name: Publish to PyPI
269
+ uses: pypa/gh-action-pypi-publish@release/v1
270
+ with:
271
+ packages-dir: dist/
272
+
@@ -0,0 +1,3 @@
1
+ src/greennode_agentbase/specs/runtime/api.json.gz
2
+ src/greennode_agentbase/specs/identity/api.json.gz
3
+ src/greennode_agentbase/specs/memory/api.json.gz
@@ -0,0 +1,367 @@
1
+ Metadata-Version: 2.4
2
+ Name: greennode-agentbase
3
+ Version: 1.0.1
4
+ Summary: An SDK for building and deploying AI agents with GreenNode AgentBase
5
+ Project-URL: Homepage, https://git.vngcloud.tech/cloud-ai-platform/greennode-agent-base-sdk
6
+ Project-URL: Bug Tracker, https://git.vngcloud.tech/cloud-ai-platform/greennode-agent-base-sdk/issues
7
+ Project-URL: Documentation, https://git.vngcloud.tech/cloud-ai-platform/greennode-agent-base-sdk
8
+ Author-email: GreenNode <opensource@greennode.ai>
9
+ License: Apache-2.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: >=3.7
25
+ Requires-Dist: click>=8.0.0
26
+ Requires-Dist: docker>=6.0.0
27
+ Requires-Dist: httpx>=0.28.1
28
+ Requires-Dist: pydantic<2.41.3,>=2.0.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Requires-Dist: starlette>=0.46.2
31
+ Requires-Dist: typing-extensions<5.0.0,>=4.13.2
32
+ Requires-Dist: uvicorn>=0.34.2
33
+ Description-Content-Type: text/markdown
34
+
35
+ # GreenNode AgentBase SDK
36
+
37
+ A Python SDK for building and deploying AI agents with GreenNode AgentBase runtime.
38
+
39
+ ## Overview
40
+
41
+ GreenNode AgentBase SDK provides a runtime framework for deploying AI agents with support for:
42
+ - HTTP endpoint handling for agent invocations
43
+ - Health status monitoring and ping endpoints
44
+ - Async task tracking
45
+ - Request context management
46
+ - Streaming responses
47
+ - Unified error handling
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install greennode-agentbase
53
+ ```
54
+
55
+ ## Quick Start
56
+
57
+ ```python
58
+ from greennode_agentbase import GreenNodeAgentBaseApp
59
+
60
+ # Create the application
61
+ app = GreenNodeAgentBaseApp()
62
+
63
+ # Define your agent handler
64
+ @app.entrypoint
65
+ def my_agent(payload: dict):
66
+ """Your agent logic here."""
67
+ query = payload.get("query", "")
68
+ # Process the query with your agent
69
+ return {"response": f"Processed: {query}"}
70
+
71
+ # Run the server
72
+ if __name__ == "__main__":
73
+ app.run(port=8080)
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ ### Basic Agent Handler
79
+
80
+ ```python
81
+ from greennode_agentbase import GreenNodeAgentBaseApp
82
+
83
+ app = GreenNodeAgentBaseApp()
84
+
85
+ @app.entrypoint
86
+ def simple_agent(payload: dict) -> dict:
87
+ """Simple agent that echoes the input."""
88
+ return {"echo": payload}
89
+ ```
90
+
91
+ ### Handler with Request Context
92
+
93
+ ```python
94
+ from greennode_agentbase import GreenNodeAgentBaseApp, RequestContext
95
+
96
+ app = GreenNodeAgentBaseApp()
97
+
98
+ @app.entrypoint
99
+ def contextual_agent(payload: dict, context: RequestContext) -> dict:
100
+ """Agent that uses request context."""
101
+ session_id = context.session_id
102
+ headers = context.request_headers or {}
103
+
104
+ return {
105
+ "result": payload,
106
+ "session_id": session_id,
107
+ "authorization": headers.get("Authorization"),
108
+ }
109
+ ```
110
+
111
+ ### Async Agent Handler
112
+
113
+ ```python
114
+ import asyncio
115
+ from greennode_agentbase import GreenNodeAgentBaseApp
116
+
117
+ app = GreenNodeAgentBaseApp()
118
+
119
+ @app.entrypoint
120
+ async def async_agent(payload: dict) -> dict:
121
+ """Async agent handler."""
122
+ # Simulate async work
123
+ await asyncio.sleep(0.1)
124
+ return {"result": "async processing complete"}
125
+ ```
126
+
127
+ ### Streaming Responses
128
+
129
+ ```python
130
+ from greennode_agentbase import GreenNodeAgentBaseApp
131
+
132
+ app = GreenNodeAgentBaseApp()
133
+
134
+ @app.entrypoint
135
+ def streaming_agent(payload: dict):
136
+ """Agent that streams responses."""
137
+ for i in range(5):
138
+ yield {"chunk": i, "data": f"chunk_{i}"}
139
+ ```
140
+
141
+ ### Custom Ping Handler
142
+
143
+ ```python
144
+ from greennode_agentbase import GreenNodeAgentBaseApp, PingStatus
145
+
146
+ app = GreenNodeAgentBaseApp()
147
+
148
+ @app.ping
149
+ def custom_health_check() -> PingStatus:
150
+ """Custom health check logic."""
151
+ # Check your system health
152
+ if system_is_busy():
153
+ return PingStatus.HEALTHY_BUSY
154
+ return PingStatus.HEALTHY
155
+ ```
156
+
157
+ ### Async Task Tracking
158
+
159
+ ```python
160
+ from greennode_agentbase import GreenNodeAgentBaseApp
161
+
162
+ app = GreenNodeAgentBaseApp()
163
+
164
+ @app.async_task
165
+ async def background_processing():
166
+ """Long-running background task."""
167
+ # This task will be tracked for health monitoring
168
+ await process_large_dataset()
169
+ ```
170
+
171
+ ### Error Handling
172
+
173
+ All SDK errors inherit from `GreenNodeAgentBaseError`:
174
+
175
+ ```python
176
+ from greennode_agentbase import (
177
+ GreenNodeAgentBaseError,
178
+ GreenNodeValidationError,
179
+ GreenNodeRuntimeError,
180
+ GreenNodeRequestError,
181
+ GreenNodeConfigurationError,
182
+ )
183
+
184
+ try:
185
+ # Your code here
186
+ pass
187
+ except GreenNodeValidationError as e:
188
+ print(f"Validation error: {e.message}")
189
+ print(f"Details: {e.details}")
190
+ except GreenNodeRuntimeError as e:
191
+ print(f"Runtime error: {e.message}")
192
+ except GreenNodeAgentBaseError as e:
193
+ print(f"SDK error: {e.message}")
194
+ ```
195
+
196
+ ## Command-line interface (CLI)
197
+
198
+ The `greennode` CLI provides deploy, memory, and runtime management. Use `greennode --help` and `greennode <group> --help` for details.
199
+
200
+ ### CLI hierarchy
201
+
202
+ ```text
203
+ greennode
204
+ ├── deploy
205
+ │ └── run Deploy agent (build, push, create runtime). Use -o id to print only the runtime id.
206
+ ├── memory
207
+ │ ├── create Create a memory
208
+ │ ├── list List memories
209
+ │ ├── get Get a memory by ID
210
+ │ └── ... (other memory subcommands)
211
+ └── runtime
212
+ ├── list List runtimes
213
+ ├── get <id> Get a runtime by ID
214
+ ├── patch <id> Update a runtime (image, flavor, env, command, args)
215
+ └── endpoints
216
+ ├── list <runtime-id> List endpoints for a runtime
217
+ ├── create <runtime-id> Create an endpoint
218
+ ├── update <runtime-id> <endpoint-id> Update endpoint (e.g. --version)
219
+ └── delete <runtime-id> <endpoint-id> Delete an endpoint
220
+ ```
221
+
222
+ ### Best practices
223
+
224
+ - **Config precedence:** Values are resolved in order: environment variables → `.greennode.json` (for `GREENNODE_CLIENT_ID`, `GREENNODE_CLIENT_SECRET`, `GREENNODE_ACCESS_CONTROL_NAME`, registry vars, etc.). Use `.greennode.json` for non-sensitive defaults and environment variables for secrets.
225
+ - **When to use which:** Use `greennode deploy run` for a full deploy (build, push, create runtime). Use `greennode runtime list`, `get`, `patch` and `greennode runtime endpoints ...` to manage runtimes and endpoints without redeploying.
226
+ - **Scripting:** After `greennode deploy run`, the runtime id is printed on its own line. Use `greennode deploy run -o id` to print only the runtime id for scripts.
227
+
228
+ ## API Reference
229
+
230
+ ### GreenNodeAgentBaseApp
231
+
232
+ Main application class for deploying agents.
233
+
234
+ #### Methods
235
+
236
+ - `entrypoint(func)` - Decorator to register the main agent handler
237
+ - `ping(func)` - Decorator to register a custom ping/health handler
238
+ - `async_task(func)` - Decorator to track async tasks
239
+ - `run(port=8080, host=None)` - Start the server
240
+ - `get_current_ping_status()` - Get current health status
241
+ - `force_ping_status(status)` - Force a specific ping status
242
+ - `add_async_task(name, metadata=None)` - Manually track an async task
243
+ - `complete_async_task(task_id)` - Mark an async task as complete
244
+
245
+ ### RequestContext
246
+
247
+ Request context model containing request metadata.
248
+
249
+ #### Attributes
250
+
251
+ - `session_id` - Optional session identifier
252
+ - `request_headers` - Optional dictionary of request headers
253
+ - `request` - Underlying Starlette request object
254
+
255
+ ### GreenNodeAgentBaseContext
256
+
257
+ Context manager for request-scoped data.
258
+
259
+ #### Methods
260
+
261
+ - `set_request_context(request_id, session_id=None)` - Set request context
262
+ - `get_request_id()` - Get current request ID
263
+ - `get_session_id()` - Get current session ID
264
+ - `set_workload_access_token(token)` - Set access token
265
+ - `get_workload_access_token()` - Get access token
266
+ - `set_request_headers(headers)` - Set request headers
267
+ - `get_request_headers()` - Get request headers
268
+
269
+ ### PingStatus
270
+
271
+ Enum for health status values:
272
+
273
+ - `HEALTHY` - Agent is healthy and ready
274
+ - `HEALTHY_BUSY` - Agent is healthy but processing requests
275
+
276
+ ## HTTP Endpoints
277
+
278
+ ### POST /invocations
279
+
280
+ Main endpoint for agent invocations.
281
+
282
+ **Request:**
283
+ ```json
284
+ {
285
+ "prompt": "your input here"
286
+ }
287
+ ```
288
+
289
+ **Response:**
290
+ ```json
291
+ {
292
+ "result": "agent output"
293
+ }
294
+ ```
295
+
296
+ ### GET /health
297
+
298
+ Health check endpoint.
299
+
300
+ **Response:**
301
+ ```json
302
+ {
303
+ "status": "Healthy",
304
+ "time_of_last_update": 1234567890
305
+ }
306
+ ```
307
+
308
+ ## Error Handling
309
+
310
+ All errors in the SDK inherit from `GreenNodeAgentBaseError`:
311
+
312
+ - `GreenNodeValidationError` - Input validation errors
313
+ - `GreenNodeRuntimeError` - Runtime execution errors
314
+ - `GreenNodeConfigurationError` - Configuration errors
315
+ - `GreenNodeRequestError` - HTTP request errors
316
+
317
+ All errors include:
318
+ - `message` - Error message
319
+ - `details` - Optional error details dictionary
320
+ - `cause` - Optional underlying exception
321
+
322
+ ## Development
323
+
324
+ ### Setup
325
+
326
+ ```bash
327
+ # Install development dependencies
328
+ pip install -e ".[dev]"
329
+
330
+ # Run tests
331
+ pytest
332
+
333
+ # Run linting
334
+ ruff check src tests
335
+
336
+ # Run type checking
337
+ mypy src
338
+ ```
339
+
340
+ ### Testing
341
+
342
+ ```bash
343
+ # Run all tests
344
+ pytest
345
+
346
+ # Run with coverage
347
+ pytest --cov=src --cov-report=html
348
+
349
+ # Run specific test file
350
+ pytest tests/greennode_agentbase/runtime/test_app.py
351
+ ```
352
+
353
+ ## License
354
+
355
+ Apache License 2.0 - see [LICENSE.txt](LICENSE.txt) for details.
356
+
357
+ ## Contributing
358
+
359
+ Contributions are welcome! Please ensure:
360
+ - All tests pass
361
+ - Code follows the style guidelines (ruff, mypy)
362
+ - New features include tests
363
+ - Documentation is updated
364
+
365
+ ## Support
366
+
367
+ For issues and questions, please use the project's issue tracker.