Skip to content

Commit e29771c

Browse files
committed
Address PR review feedback on skill documentation
- Fix SQLLitePersister → SQLitePersister across all files (canonical name) - Fix Input import: from burr.core → from burr.core.action - Fix infinite self-loop in parallel execution example (add Result action) - Deduplicate State Management section from SKILL.md (defer to patterns.md) - Trim verbose filler content in SKILL.md and patterns.md - Simplify branching decision tree example in patterns.md
1 parent f07a4c3 commit e29771c

5 files changed

Lines changed: 51 additions & 273 deletions

File tree

.claude/plugins/burr/skills/burr/SKILL.md

Lines changed: 5 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -122,164 +122,18 @@ When users encounter problems:
122122

123123
### 5. Adding Features
124124

125-
Common enhancement requests:
125+
See [api-reference.md](api-reference.md) for streaming, async, and parallel execution APIs. See [examples.md](examples.md) for working code.
126126

127-
**Streaming responses**:
128-
```python
129-
@action(reads=["input"], writes=["output"])
130-
def streaming_action(state: State) -> Generator[State, None, Tuple[dict, State]]:
131-
for chunk in stream_data():
132-
yield state.update(current_chunk=chunk)
133-
result = {"output": final_result}
134-
return result, state.update(**result)
135-
```
136-
137-
**Async actions**:
138-
```python
139-
@action(reads=["data"], writes=["result"])
140-
async def async_action(state: State) -> State:
141-
result = await fetch_data()
142-
return state.update(result=result)
143-
```
144-
145-
**Parallel execution**:
146-
```python
147-
from burr.core.parallelism import MapStates, RunnableGraph
148-
149-
# Apply same action to multiple states
150-
class TestMultiplePrompts(MapStates):
151-
def action(self, state: State, inputs: dict) -> Action | Callable | RunnableGraph:
152-
return query_llm.with_name("query_llm")
153-
154-
def states(self, state: State, context: ApplicationContext, inputs: dict):
155-
for prompt in state["prompts"]:
156-
yield state.update(prompt=prompt)
157-
158-
def reduce(self, state: State, states):
159-
results = [s["result"] for s in states]
160-
return state.update(all_results=results)
161-
162-
@property
163-
def reads(self) -> list[str]:
164-
return ["prompts"]
165-
166-
@property
167-
def writes(self) -> list[str]:
168-
return ["all_results"]
169-
170-
app = ApplicationBuilder().with_actions(
171-
multi_prompt=TestMultiplePrompts()
172-
).build()
173-
```
174-
175-
## State Management Patterns
176-
177-
### Regular State (Dictionary-Based)
178-
179-
**Reading from state:**
180-
```python
181-
# Use bracket notation to access state values
182-
value = state["key"]
183-
chat_history = state["chat_history"]
184-
counter = state["counter"]
185-
```
186-
187-
**Updating state:**
188-
State is immutable. Methods return NEW State objects:
189-
```python
190-
# state.update() - set/update keys, returns new State
191-
new_state = state.update(counter=5, name="Alice")
192-
193-
# state.append() - append to lists, returns new State
194-
new_state = state.append(chat_history={"role": "user", "content": "hi"})
195-
196-
# state.increment() - increment numbers, returns new State
197-
new_state = state.increment(counter=1)
198-
199-
# Chaining - each method returns a State, enabling fluent patterns
200-
new_state = state.update(prompt=prompt).append(chat_history=item)
201-
```
202-
203-
**Action return pattern:**
204-
Actions return `Tuple[dict, State]`:
205-
```python
206-
from typing import Tuple
207-
208-
@action(reads=["prompt"], writes=["response", "chat_history"])
209-
def ai_respond(state: State) -> Tuple[dict, State]:
210-
# 1. Read from state
211-
prompt = state["prompt"]
212-
213-
# 2. Process
214-
response = call_llm(prompt)
215-
216-
# 3. Return (result_dict, new_state)
217-
# result_dict is exposed to callers/tracking
218-
# new_state is the updated immutable state
219-
return {"response": response}, state.update(response=response).append(
220-
chat_history={"role": "assistant", "content": response}
221-
)
222-
```
223-
224-
**Shorthand (also valid):**
225-
```python
226-
@action(reads=["counter"], writes=["counter"])
227-
def increment(state: State) -> State:
228-
result = {"counter": state["counter"] + 1}
229-
# Framework infers result from state updates
230-
return state.update(**result)
231-
```
232-
233-
### Pydantic Typed State (Different Pattern)
234-
235-
**Define state model:**
236-
```python
237-
from pydantic import BaseModel, Field
238-
from typing import Optional
239-
240-
class ApplicationState(BaseModel):
241-
prompt: Optional[str] = Field(default=None, description="User prompt")
242-
response: Optional[str] = Field(default=None, description="AI response")
243-
chat_history: list[dict] = Field(default_factory=list)
244-
```
245-
246-
**Configure application:**
247-
```python
248-
from burr.integrations.pydantic import PydanticTypingSystem
249-
250-
app = (
251-
ApplicationBuilder()
252-
.with_typing(PydanticTypingSystem(ApplicationState))
253-
.with_state(ApplicationState())
254-
.build()
255-
)
256-
```
257-
258-
**Access typed state:**
259-
```python
260-
# Use attribute access (not bracket notation)
261-
@action.pydantic(reads=["prompt"], writes=["response"])
262-
def ai_respond(state: ApplicationState) -> ApplicationState:
263-
# 1. Read using attributes
264-
prompt = state.prompt
265-
266-
# 2. Process
267-
response = call_llm(prompt)
268-
269-
# 3. Mutate in-place and return state
270-
# (Mutation happens on internal copy)
271-
state.response = response
272-
return state
273-
```
127+
## State Management Quick Reference
274128

275-
**Key differences:**
129+
Burr supports two state patterns. See [patterns.md](patterns.md) for full details and examples.
276130

277131
| Aspect | Regular State | Pydantic Typed State |
278132
|--------|---------------|---------------------|
279133
| **Access** | `state["key"]` | `state.key` |
280134
| **Return** | `Tuple[dict, State]` | `ApplicationState` |
281135
| **Decorator** | `@action(reads=[], writes=[])` | `@action.pydantic(reads=[], writes=[])` |
282-
| **Updates** | Must use `.update()`, `.append()` | In-place mutation |
136+
| **Updates** | `.update()`, `.append()`, `.increment()` | In-place mutation |
283137
| **Type Safety** | Runtime only | IDE support + validation |
284138

285139
## Code Quality Standards
@@ -298,7 +152,7 @@ When writing or reviewing Apache Burr code:
298152
- **Loops**: Use recursive transitions with conditions
299153
- **Error handling**: Create error actions and transition to them on failure
300154
- **Multi-step workflows**: Chain actions with clear single responsibilities
301-
- **State persistence**: Use `SQLLitePersister` or `initialize_from` for resumability
155+
- **State persistence**: Use `SQLitePersister` or `initialize_from` for resumability
302156
- **Observability**: Always include `.with_tracker()` for the Burr UI
303157

304158
## Integration Scenarios

.claude/plugins/burr/skills/burr/api-reference.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,9 @@ app = (
574574

575575
**SQLite Persister:**
576576
```python
577-
from burr.core.persistence import SQLLitePersister
577+
from burr.core.persistence import SQLitePersister
578578

579-
persister = SQLLitePersister(
579+
persister = SQLitePersister(
580580
db_path="app.db",
581581
table_name="burr_state",
582582
connect_kwargs={"check_same_thread": False}
@@ -709,7 +709,7 @@ app = (
709709
Special action that captures runtime inputs:
710710

711711
```python
712-
from burr.core import Input
712+
from burr.core.action import Input
713713

714714
app = (
715715
ApplicationBuilder()

.claude/plugins/burr/skills/burr/examples.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ Execute multiple actions in parallel using Apache Burr's parallelism APIs.
353353

354354
```python
355355
from burr.core.parallelism import MapActions, RunnableGraph
356-
from burr.core import action, State, ApplicationContext
356+
from burr.core import action, State, ApplicationContext, Result
357357
from typing import Dict, Any
358358

359359
@action(reads=["text"], writes=["sentiment"])
@@ -403,8 +403,11 @@ class ParallelTextAnalysis(MapActions):
403403

404404
app = (
405405
ApplicationBuilder()
406-
.with_actions(parallel_analysis=ParallelTextAnalysis())
407-
.with_transitions(("parallel_analysis", "parallel_analysis")) # Or continue to next action
406+
.with_actions(
407+
parallel_analysis=ParallelTextAnalysis(),
408+
done=Result("analysis"),
409+
)
410+
.with_transitions(("parallel_analysis", "done"))
408411
.with_state(text="Sample text to analyze")
409412
.with_entrypoint("parallel_analysis")
410413
.build()
@@ -416,7 +419,7 @@ app = (
416419
Save and resume application state.
417420

418421
```python
419-
from burr.core.persistence import SQLLitePersister
422+
from burr.core.persistence import SQLitePersister
420423

421424
@action(reads=["step"], writes=["step", "result"])
422425
def long_running_step(state: State, step_name: str) -> State:
@@ -428,7 +431,7 @@ def long_running_step(state: State, step_name: str) -> State:
428431
)
429432

430433
# Set up persister
431-
persister = SQLLitePersister(
434+
persister = SQLitePersister(
432435
db_path="~/.burr/my_app.db",
433436
table_name="app_state"
434437
)

0 commit comments

Comments
 (0)