Problem statement
In patterns/agents/orchestrator_workers.ipynb, FlexibleOrchestrator.process() passes the context dict into both prompt-building calls via **context:
orchestrator_input = self._format_prompt(self.orchestrator_prompt, task=task, **context)
...
worker_input = self._format_prompt(
self.worker_prompt,
original_task=task,
task_type=task_info["type"],
task_description=task_info["description"],
**context,
)But ORCHESTRATOR_PROMPT only defines {task}, and WORKER_PROMPT only defines {original_task}, {task_type}, {task_description}. Neither template references {target_audience} or {key_features} — the exact keys used in the notebook's own example call at the bottom of the notebook.
Since str.format(**kwargs) silently ignores any kwargs that don't match a placeholder in the template, target_audience and key_features never reach the model — the example appears to demonstrate context-aware generation but the context has no actual effect on the output.
This also creates a latent collision risk: if a context dict ever contained a key matching one of the fixed kwarg names (task, original_task, task_type, task_description), _format_prompt would raise TypeError: got multiple values for keyword argument.
Proposed fix
Stop interpolating context into the prompt templates via named placeholders (which requires every template to declare every possible context key, and risks the kwarg collision above). Instead, render context as its own appended block regardless of which keys it contains:
def _build_context_block(self, context: dict) -> str:
if not context:
return ""
lines = [f"{key}: {value}" for key, value in context.items()]
return "\n\nAdditional context:\n" + "\n".join(lines)Then append this block to orchestrator_input / worker_input after formatting the fixed placeholders, rather than passing **context into _format_prompt. This way any context dict reaches the model regardless of its keys, and there's no more collision risk with fixed kwarg names.
PR
Fixed in #836
Confirmed — this is exactly what
str.format(**kwargs)does: it only substitutes kwargs that match a{placeholder}in the template, and any extra keys are silently discarded rather than raising. There's noKeyErrorfor unused kwargs, only for placeholders missing a value, so the context fields disappear without any signal, and the notebook's example ends up demonstrating "context-aware" generation that isn't actually context-aware.Beyond appending a context block, it'd be worth adding a cheap runtime guard for this class of bug generally: run the template through
string.Formatter().parse(template), collect the field names it references, and diff that against the kwargs passed in. Any kwarg not in the referenced set means dead context — raise orwarnings.warninstead of silently no-op'ing. That catches future template edits that drop a placeholder, not just this one instance. Worth calling out since this pattern is easy to copy into production prompt-building code and fail the same way with zero visible error.