This release refactors Flow Mode workflows so that the runner is passed as the
first argument to your workflow function. The change eliminates the shared
Vibecore.runner instance state and makes concurrent Vibecore.run() calls
safe by design.
- Concurrency safety – each workflow invocation receives its own runner instance, preventing race conditions across tasks.
- Explicit dependencies – the workflow signature clearly communicates that user interaction helpers come from the runner.
- Simpler reasoning – no more hidden state on the
Vibecoreobject and no need forContextVarindirection.
@vibecore.workflow()
async def logic(
runner: VibecoreRunnerBase[MyContext, MyResult],
) -> MyResult:
...| Old API | New API | Notes |
|---|---|---|
await vibecore.user_input() |
await runner.user_input() |
Reads from CLI/Textual/static inputs |
await vibecore.print() |
await runner.print() |
Emits status messages |
await vibecore.run_agent() |
await runner.run_agent() |
Runs agents with streaming + sessions |
The Vibecore.run_agent() helper now raises a RuntimeError to surface the
breaking change early.
- Add
runneras the first parameter to every function decorated with@vibecore.workflow(). - Update imports to include
VibecoreRunnerBasewhen you need explicit typing for the runner argument. - Replace
vibecore.user_input/print/run_agentcalls with the runner equivalents. - Access context and session from the runner via
runner.contextandrunner.sessionwhen you need them. - Re-run your tests (including
uv run pyright) to verify typing and runtime behavior.
Before
@vibecore.workflow()
async def logic(context: MyContext | None, session: Session) -> str:
message = await vibecore.user_input("Enter message:")
await vibecore.print(f"Processing: {message}")
result = await vibecore.run_agent(agent, message, context=context, session=session)
return result.final_outputAfter
@vibecore.workflow()
async def logic(
runner: VibecoreRunnerBase[MyContext, RunResultBase],
) -> str:
message = await runner.user_input("Enter message:")
await runner.print(f"Processing: {message}")
result = await runner.run_agent(
agent,
message,
context=runner.context,
session=runner.session,
)
return result.final_output-
uv run pytest -
uv run ruff check . -
uv run pyright
All Flow Mode examples and docs in the repository have been updated to follow the new runner-first convention. Use them as references while updating your own applications.