Agent$invoke(), Workflow$run() / $resume(), WorkflowAgent$invoke()
and LeadAgent$invoke() / $resume() gain stream = FALSE and
on_event = NULL arguments, so you can follow their progress while they
run instead of waiting for the final answer:
stream = TRUE prints an Agent's tokens to the console as they are
generated. Supplying an on_event callback (which implies streaming)
delivers every unit of progress as a mini007_event - a list with a type
discriminator ("text_delta", "tool_call", "tool_result",
"station_started", "station_completed", "station_retry",
"hitl_request", "workflow_output", "task_started", "lead_output",
...), the emitting source, a text payload and a data list.
See ?mini007_event.stream = TRUE and no callback,
Agent$invoke() returns it invisibly since it was already printed.station/step in a Workflow, task/agent in a
LeadAgent), so one callback on a LeadAgent sees the tokens of an Agent
running inside a Workflow registered via $as_agent().on_event cancels the run with a
mini007_stream_cancelled condition; Workflow retries and fallbacks never
swallow it, and the Agent's message history and cost stay in sync with
what the LLM produced before the cancellation.mirai daemons and emit only
start/completion events; the callback is never sent to a daemon.invoke() takes a single argument keep working
inside a streamed Workflow or LeadAgent; they just don't stream tokens.Two related failures previously surfaced as a cryptic internal error -
Error in vapply(): ! values must be length 1, but FUN(X[[1]]) result is length 0 - deep inside Agent$invoke()'s message-sync internals, with no
indication of what actually went wrong:
$invoke() (and every other direct LLM
call inside Agent and LeadAgent) now catches the raw provider error and
raises a clear, actionable message explaining the likely cause, while still
preserving the original error for debugging.ellmer records this as a result with an
empty value and an error attached; mini007 was feeding that empty value
straight into sprintf(), which silently produced a zero-length string and
crashed the vapply() call that assembles message history. $invoke() now
survives this and records the actual tool error (e.g. "ERROR: connection refused: weather API is down") in the conversation history instead of
crashing.HITL no longer requires a blocking readline() prompt inside an interactive
console. $set_hitl() on both Workflow and LeadAgent gains a mode
argument:
mode = "console" (default) — unchanged: blocks on readline() exactly as
before.mode = "pause" — $run() / $invoke() return immediately with a
mini007_pending object describing the paused step instead of blocking.
Inspect it, then call the new $resume(request_id, action, value) method
(action is one of "continue", "edit", "abort") to continue
execution from that point.This makes HITL usable outside an interactive console - e.g. from a Shiny app, a Plumber endpoint, or any batch job that needs to persist a paused run and resume it later.
New:
Workflow$resume() / LeadAgent$resume()is_pending() — check whether a value is a paused mini007_pending objectChanged:
Workflow$set_hitl() / LeadAgent$set_hitl() gain a mode argument
("console" default, "pause")Major feature addition enabling 2-4x speedup for independent processing units.
New Methods:
$set_daemons(n) — Configure n parallel worker processes using mirai package$add_parallel_group(from, stations, to, merge_fn) — Define stations to execute concurrently
from: predecessor stationstations: vector of station names to run in parallelto: optional successor station (receives merged results)merge_fn: custom function to combine parallel results (default: newline concatenation)Enhanced Methods:
$visualize() — Now displays parallel routes in red with ∥ symbol to distinguish from sequential routesUse Cases:
Performance:
Agent and WorkflowAgent handlersDocumentation:
workflow.qmd with working exampleexample_real_llm.R demonstrating 3 parallel agents analyzing "AI in Healthcare"Technical Details:
Built on mirai package for reliable async execution
Each parallel station inherits retry/fallback configuration
Parallel results automatically cached with same mechanism as sequential stations
Graceful daemon cleanup and reinitialization
Adding the per-station retry features to the Workflow class
Adding the fallback handlers to the Workflow class
share_context_with()register_tools()list_tools()remove_tools()clear_tools()generate_and_register_tool()mini007 and ellmerAdding the following new methods:
validate_response()clone_agent()visualize_plan() method as the DiagrammeR package has many dependencies.add_message method for compatibility with ellmer Turnsellmer as an import dependency.generate_execute_r_code() method.messages as an active R6 field. It is now possible to modify the messages that will be used by the LLM object through a list object. The list object will be automatically converted to the corresponding ellmer Turns.Adding the following new methods:
keep_last_n_messages()update_instruction()clear_and_summarise_messages()judge_and_choose_best_response()set_budget()export_messages_history() and load_messages_history()reset_conversation_history()add_message()generate_execute_r_code()visualize_plan()set_budget_policy()Adding the following new parameters:
force_regenerate_plan boolean parameter to the invoke method of the LeadAgent, this will allow taking into account if the LeadAgent has already generated a plan or not. If a plan is detected, no need to generate the plan from scratch, except if the user set the force_generate_plan to TRUE.Deleting the following method:
delegate_prompt(), not needed anymore as the generate_plan() method has the same behavior.