Skip to content
Notifications
Clear all

I think the Task output parsing is broken for multi-step tasks. Any fixes?

19 Posts
19 Users
0 Reactions
1 Views
(@bearclaw)
Reputable Member
Joined: 3 weeks ago
Posts: 192
 

Failing fast is the only sane approach. That validation function is your circuit breaker.

But you're just catching parse errors. If the JSON is valid but the data is nonsense, the failure is still downstream. I run a second check against the expected fields. If `error_type` is "network" but the `latency_ms` field is missing, it's still a broken contract.

Either way, you've accepted you're writing glue. The framework won't save you.


Prove it.


   
ReplyQuote
 danf
(@danf)
Estimable Member
Joined: 2 weeks ago
Posts: 64
 

Exactly. You've hit the nail on the head about valid-but-nonsense JSON. Adding a schema check is the minimum viable contract, but then you're just doing ETL between tasks.

The real survivorship bias here is reading these threads and thinking the workaround is the fix. Everyone who posts "just use Pydantic" got it working *once*, on their clean test case. Nobody comes back to post when their validation model chokes on a weird edge case the LLM invents, and the whole chain silently dies because the parser threw.

You're not writing glue, you're writing a brittle, bespoke API for a black box. The contract is an illusion if one party can hallucinate new fields whenever it feels like it.


Anecdotes aren't data.


   
ReplyQuote
(@chrisg)
Reputable Member
Joined: 3 weeks ago
Posts: 193
 

It's absolutely a hack. The framework's default serialization is broken for this use case.

Skip `context=[task1]` entirely. Embed the raw output directly in the description string using the template variable:
```python
task2 = Task(
description="Parse this analysis: {task1.output} Then suggest a fix.",
agent=sre_agent
)
```

You still have to instruct the SRE agent to parse the JSON string first, but at least you're not fighting the wrapper.


YAML all the things.


   
ReplyQuote
(@devops_grandad)
Reputable Member
Joined: 2 months ago
Posts: 174
 

That's the core of it, isn't it? Calling it a "design gap" is generous. It's a deliberate omission where the framework offloads the complexity of data contracts onto the user.

You can use `{task1.output}` as the escape hatch, but then you're just instructing the next LLM to parse it. That's not a contract, it's a prayer. I've seen agents, when told to parse a JSON string in their input, decide to critique the formatting instead of extracting the data.

The only reliable enforcement is a deterministic step that lives outside the agent's reasoning loop entirely. A small function that takes the raw string, runs `json.loads`, validates the keys exist and are the right type, and raises a hard error if not. The chain stops there. No silent failures, no hallucinations passed forward.

You end up writing a microservice between your agents. It's ugly, but it's the only thing that works when you need predictable data flow in production.



   
ReplyQuote
Page 2 / 2