mohd-faraz

_blogs

// blogs / 20260720.md

Dev Log: July 20 Wrap-up

2026-07-20
#python#workflow-engine#json-parsing#backend

Overview

Today was mostly about tightening up how data moves through our workflow engine. I spent a good chunk of time dealing with variable interpolation, cleaning up what we actually store in our logs, and fixing some session identification logic that was a bit tangled.

What I Worked On

Making email templates smarter

I spent some time on the email node today. We needed a way to let users reach deep into their data payloads using a {{payload.key}} syntax. It sounds simple, but when you're dealing with nested dictionaries and stringified JSON that needs to be parsed on the fly, it gets a bit recursive.

I implemented a "smart unwrap" logic that tries to detect if a value is a JSON string and automatically parses it so the user can keep traversing the path. It saves the user from having to manually add a JSON parsing node before every email.

Keeping the logs lean

Our logs were getting a bit noisy, and I realized we were trying to serialize objects that really have no business being in a JSON log—specifically heavy session resources and internal tool objects. I updated our serialization utility to explicitly skip these keys.

def sanitize_for_logging(obj):
    if isinstance(obj, dict):
        # We don't need to log raw session resources or internal function pointers
        return {k: sanitize_for_logging(v) for k, v in obj.items() if k not in ('session_resource', 'tools_obj')}
    elif isinstance(obj, list):
        return [sanitize_for_logging(item) for item in obj]
    return obj

AI Agent Memory & Session Headers

I decided to disable a generic fallback mechanism in our AI agent nodes. Previously, if it couldn't find user-specific memory, it would try to pull the most recent messages from the general flow context. It sounds helpful in theory, but in practice, it was creating some confusing context-bleeding. Better to have no memory than the wrong memory.

I also had a bit of a back-and-forth with our workflow decorator. I had to revert and then re-fix how we pass session and user IDs in the headers. We need to distinguish between the X-Chat-Session-Id (the specific conversation) and the X-Client-User-Id (who the user actually is). It's a small change, but if those get swapped, the entire state management for the chat falls apart.

Wrapping Up

It feels good to clear out some of these "papercut" bugs. The variable interpolation stuff in particular should make life a lot easier for anyone building complex flows. Tomorrow, I'll probably look into commonizing that interpolation logic so we can use it across other nodes, not just emails.

Catch you later.