Skip to content

Commit 0c1e9f1

Browse files
Enhance documentation and introduce model-based parameters for graph definitions (Beta) (#349)
* Enhance documentation and introduce model-based parameters for graph definitions (Beta) - Updated README.md to reflect the new model-based approach for defining graphs, including examples for both JSON and Python SDK usage. - Added a new API changes document detailing the model-based parameters for the `upsert_graph` method, improving type safety and validation. - Enhanced create-graph.md to include beta features for creating graph templates using model-based parameters. - Updated retry-policy.md to introduce model-based configuration for retry policies, emphasizing benefits like type safety and IDE support. - Incremented version to 0.0.2b6 to reflect the addition of new features and documentation updates. * Update docs/docs/exosphere/api-changes.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs/docs/exosphere/retry-policy.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 27249fc commit 0c1e9f1

7 files changed

Lines changed: 594 additions & 37 deletions

File tree

‎README.md‎

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ This allows developers to deploy production agents that can scale beautifully to
7171
).start()
7272
```
7373

74-
- ### Define your first graph
74+
- ### Define your first graph (Beta)
7575

76-
Graphs are then described connecting nodes with relationships in json objects. Exosphere runs graph as per defined trigger conditions. See [Graph definitions](https://docs.exosphere.host/exosphere/create-graph/) to see more examples.
76+
Graphs can be defined using JSON objects or with the new model-based Python SDK (beta) for better type safety and validation. See [Graph definitions](https://docs.exosphere.host/exosphere/create-graph/) for more examples.
77+
78+
**JSON Definition (Traditional):**
7779
```json
7880
{
7981
"secrets": {},
@@ -83,17 +85,47 @@ This allows developers to deploy production agents that can scale beautifully to
8385
"namespace": "hello-world",
8486
"identifier": "describe_city",
8587
"inputs": {
86-
"bucket_name": "initial",
87-
"prefix": "initial",
88-
"files_only": "true",
89-
"recursive": "false"
88+
"city": "initial"
9089
},
9190
"next_nodes": []
9291
}
9392
]
9493
}
9594
```
9695

96+
**Model-Based Definition (Beta):**
97+
```python
98+
from exospherehost import StateManager, GraphNodeModel, RetryPolicyModel, RetryStrategyEnum
99+
100+
async def create_graph():
101+
state_manager = StateManager(namespace="hello-world")
102+
103+
graph_nodes = [
104+
GraphNodeModel(
105+
node_name="MyFirstNode",
106+
namespace="hello-world",
107+
identifier="describe_city",
108+
inputs={"city": "initial"},
109+
next_nodes=[]
110+
)
111+
]
112+
113+
# Optional: Define retry policy (beta)
114+
retry_policy = RetryPolicyModel(
115+
max_retries=3,
116+
strategy=RetryStrategyEnum.EXPONENTIAL,
117+
backoff_factor=2000
118+
)
119+
120+
# Create graph with model-based approach (beta)
121+
result = await state_manager.upsert_graph(
122+
graph_name="my-first-graph",
123+
graph_nodes=graph_nodes,
124+
secrets={},
125+
retry_policy=retry_policy # beta
126+
)
127+
```
128+
97129
## Quick Start with Docker Compose
98130

99131
Get Exosphere running locally in under 2 minutes:

‎docs/docs/exosphere/api-changes.md‎

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# API Changes (Beta)
2+
3+
This document outlines the latest beta API changes and enhancements in ExosphereHost.
4+
5+
## StateManager.upsert_graph() - Model-Based Parameters (Beta)
6+
7+
The `upsert_graph` method now supports model-based parameters for improved type safety, validation, and developer experience.
8+
9+
### New Signature
10+
11+
```python
12+
async def upsert_graph(
13+
self,
14+
graph_name: str,
15+
graph_nodes: list[GraphNodeModel],
16+
secrets: dict[str, str],
17+
retry_policy: RetryPolicyModel | None = None,
18+
store_config: StoreConfigModel | None = None,
19+
validation_timeout: int = 60,
20+
polling_interval: int = 1
21+
):
22+
```
23+
24+
### Key Changes
25+
26+
1. **Model-Based Nodes**: `graph_nodes` parameter now expects a list of `GraphNodeModel` objects instead of raw dictionaries
27+
2. **Retry Policy Model**: Optional `retry_policy` parameter using `RetryPolicyModel` with enum-based strategy selection
28+
3. **Store Configuration**: Optional `store_config` parameter using `StoreConfigModel` for graph-level key-value store
29+
4. **Validation Control**: New `validation_timeout` and `polling_interval` parameters for better control over graph validation
30+
31+
### Migration Guide
32+
33+
#### Before (Traditional)
34+
```python
35+
# Old dictionary-based approach
36+
graph_nodes = [
37+
{
38+
"node_name": "DataProcessor",
39+
"namespace": "MyProject",
40+
"identifier": "processor",
41+
"inputs": {"data": "initial"},
42+
"next_nodes": []
43+
}
44+
]
45+
46+
retry_policy = {
47+
"max_retries": 3,
48+
"strategy": "EXPONENTIAL",
49+
"backoff_factor": 2000
50+
}
51+
```
52+
53+
#### After (Beta Model-Based)
54+
```python
55+
from exospherehost import GraphNodeModel, RetryPolicyModel, RetryStrategyEnum
56+
57+
# New model-based approach
58+
graph_nodes = [
59+
GraphNodeModel(
60+
node_name="DataProcessor",
61+
namespace="MyProject",
62+
identifier="processor",
63+
inputs={"data": "initial"},
64+
next_nodes=[]
65+
)
66+
]
67+
68+
retry_policy = RetryPolicyModel(
69+
max_retries=3,
70+
strategy=RetryStrategyEnum.EXPONENTIAL, # Use enum instead of string
71+
backoff_factor=2000
72+
)
73+
```
74+
75+
### Available Models
76+
77+
#### GraphNodeModel
78+
- **node_name** (str): Class name of the node
79+
- **namespace** (str): Namespace where node is registered
80+
- **identifier** (str): Unique identifier in the graph
81+
- **inputs** (dict[str, Any]): Input values for the node
82+
- **next_nodes** (Optional[List[str]]): List of next node identifiers
83+
- **unites** (Optional[UnitesModel]): Unite configuration for parallel execution
84+
85+
#### RetryPolicyModel (Beta)
86+
- **max_retries** (int): Maximum number of retry attempts (default: 3)
87+
- **strategy** (RetryStrategyEnum): Retry strategy using enum values (default: EXPONENTIAL)
88+
- **backoff_factor** (int): Base delay in milliseconds (default: 2000)
89+
- **exponent** (int): Exponential multiplier (default: 2)
90+
- **max_delay** (int | None): Maximum delay cap in milliseconds (optional)
91+
92+
#### StoreConfigModel (Beta)
93+
- **required_keys** (list[str]): Keys that must be present in the store
94+
- **default_values** (dict[str, str]): Default values for store keys
95+
96+
### Retry Strategy Enums
97+
98+
- `RetryStrategyEnum.EXPONENTIAL`: Pure exponential backoff
99+
- `RetryStrategyEnum.EXPONENTIAL_FULL_JITTER`: Exponential with full randomization
100+
- `RetryStrategyEnum.EXPONENTIAL_EQUAL_JITTER`: Exponential with 50% randomization
101+
102+
- `RetryStrategyEnum.LINEAR`: Linear backoff
103+
- `RetryStrategyEnum.LINEAR_FULL_JITTER`: Linear with full randomization
104+
- `RetryStrategyEnum.LINEAR_EQUAL_JITTER`: Linear with 50% randomization
105+
106+
- `RetryStrategyEnum.FIXED`: Fixed delay
107+
- `RetryStrategyEnum.FIXED_FULL_JITTER`: Fixed with full randomization
108+
- `RetryStrategyEnum.FIXED_EQUAL_JITTER`: Fixed with 50% randomization
109+
110+
### Complete Example
111+
112+
```python
113+
from exospherehost import (
114+
StateManager,
115+
GraphNodeModel,
116+
RetryPolicyModel,
117+
StoreConfigModel,
118+
RetryStrategyEnum
119+
)
120+
121+
async def create_advanced_graph():
122+
state_manager = StateManager(namespace="MyProject")
123+
124+
# Define nodes using models
125+
graph_nodes = [
126+
GraphNodeModel(
127+
node_name="DataLoader",
128+
namespace="MyProject",
129+
identifier="loader",
130+
inputs={"source": "initial"},
131+
next_nodes=["processor"]
132+
),
133+
GraphNodeModel(
134+
node_name="DataProcessor",
135+
namespace="MyProject",
136+
identifier="processor",
137+
inputs={"data": "${{ loader.outputs.data }}"},
138+
next_nodes=[]
139+
)
140+
]
141+
142+
# Define retry policy with enum
143+
retry_policy = RetryPolicyModel(
144+
max_retries=5,
145+
strategy=RetryStrategyEnum.EXPONENTIAL_FULL_JITTER,
146+
backoff_factor=1000,
147+
exponent=2,
148+
max_delay=30000
149+
)
150+
151+
# Define store configuration
152+
store_config = StoreConfigModel(
153+
required_keys=["cursor", "batch_id"],
154+
default_values={
155+
"cursor": "0",
156+
"batch_size": "100"
157+
}
158+
)
159+
160+
# Create graph with all beta features
161+
result = await state_manager.upsert_graph(
162+
graph_name="advanced-workflow",
163+
graph_nodes=graph_nodes,
164+
secrets={"api_key": "your-key"},
165+
retry_policy=retry_policy, # beta
166+
store_config=store_config, # beta
167+
validation_timeout=120,
168+
polling_interval=2
169+
)
170+
171+
return result
172+
```
173+
174+
### Benefits
175+
176+
1. **Type Safety**: Pydantic models catch configuration errors at definition time
177+
2. **IDE Support**: Better autocomplete, error detection, and documentation
178+
3. **Validation**: Automatic validation of parameters and relationships
179+
4. **Consistency**: Standardized parameter names and types across the SDK
180+
5. **Extensibility**: Easy to add new fields and maintain backward compatibility
181+
182+
### Beta Status
183+
184+
These features are currently in beta and the API may change based on user feedback. The traditional dictionary-based approach will continue to work alongside the new model-based approach.
185+
186+
For questions or feedback about these beta features, please reach out through our [Discord community](https://discord.com/invite/zT92CAgvkj).

0 commit comments

Comments
 (0)