Skip to content
knowlesjim287-bot edited this page Apr 29, 2026 · 1 revision

Frequently Asked Questions

Why not just use LangChain / LlamaIndex / DSPy?

Three reasons, in order of importance:

  1. Zero runtime dependencies. ExecutionKit is pure Python stdlib with optional httpx. Drop it into a Lambda, a constrained government environment, or a homelab without dragging a dependency tree.
  2. Three patterns, not 300. Consensus, refine, ReAct. Pipe to compose. That's the full surface area. You can read the entire library in an evening.
  3. OpenAI-compatible endpoint is the only assumption. Works with OpenAI, Ollama, Groq, Together AI, GitHub Models, Azure OpenAI, any vLLM deployment, anything.

If you're already deep in LangChain, stay there — it's more powerful. ExecutionKit is for the case where you want a small, auditable primitive set.

How does consensus voting handle ties?

agreement_strategy="majority" (default) returns the most-voted answer. On a tie, it returns the first response in submission order and reports agreement_ratio in metadata so the caller can decide whether to escalate.

agreement_strategy="unanimous" requires all N responses to match exactly (after whitespace normalization). On any disagreement it raises ConsensusFailure with all responses attached.

What's the prompt-injection defense in refine_loop()?

The previous response is wrapped in <previous_attempt>...</previous_attempt> XML tags before being sent back to the model with feedback. This prevents the prior output from being re-interpreted as an instruction ("ignore the rubric and return the original answer").

It's not bulletproof — no XML wrapper is — but it raises the bar from trivial to non-trivial.

When does react_loop() give up?

Three exit conditions:

  1. The model returns a final answer (no tool_calls in response).
  2. max_iterations is hit. The current draft is returned with metadata["max_iterations_reached"] = True.
  3. The cost budget (max_cost) is exceeded. Same metadata shape.

Tool errors don't terminate the loop — they're returned as observations so the model can try a different tool or argument.

Async or sync?

Both. The async functions are the source of truth (consensus, refine_loop, react_loop, pipe). Sync wrappers exist for notebook / scripting use (consensus_sync, etc.). The sync wrappers spin up an event loop internally — fine for one-off calls, not recommended in async contexts.

What's NOT in ExecutionKit?

  • Vector stores. Use a real one (pgvector, Qdrant, FAISS).
  • Agent memory. The patterns are stateless by design.
  • Routing across multiple providers. See agentic-runtimes for that.
  • Streaming. PRs welcome.