The casting call still ships. The path is what an auditor will ask you to replay.
CrewAI got famous by letting you hire agents. Flows exists because hiring is not a control plane.
I said yesterday that Microsoft productized the coordination patterns people were already arguing about and gave them import paths. CrewAI made the opposite concession. The role, the goal, and the backstory are still in the file. What changed is you can put a state machine under them when tomorrow’s run has to be the same path as today’s.
That is the honest evolution for a framework that started as a casting call.
I covered CrewAI in May as the framework that wins the demo. That piece still holds. An agent has a role, a goal, a backstory, and tools. A task has a description and an expected output. A crew binds them sequential or hierarchical. Product managers can read the file. That legibility is why teams pick it up, and it is why they stay too long after the work stops being a pipeline.
The current package is 1.15.16, published August 14. GitHub and PyPI agree on the tag. The repo sits at 57,190 stars, MIT license, still shipping on a near-daily cadence: nine tagged releases after 1.15.7 on July 26. The tree was pushed this morning. Whatever else you think about the abstraction, this is not a museum.
Flows is not the news in 1.15. It has been the production control layer for a while: @start, @listen, @router, a Pydantic state object, kickoff() and kickoff_async(). A method emits. Another method listens. A router returns a label and the graph takes that branch. You can still stand up a crew inside a listener when a step is actually generative. The crew is a node. The flow is the path.
from crewai.flow import Flow, listen, router, start
from pydantic import BaseModel
class PacketState(BaseModel):
case_id: str
eligibility: str | None = None
class PriorAuthFlow(Flow[PacketState]):
@start()
def intake(self):
return self.state.case_id
@listen(intake)
def check_eligibility(self):
result = eligibility_crew.kickoff(
inputs={"case_id": self.state.case_id}
)
self.state.eligibility = result.raw
return result.raw
@router(check_eligibility)
def branch(self):
if self.state.eligibility == "ineligible":
return "deny"
return "clinical"That split is the product. A crew can still write the letter. A router decides whether the letter is allowed to exist.
It is also still a framework. August’s question is whether the thing you define still runs after the process dies. CrewAI’s answer is persistence you turn on, backed by a local store unless you replace it. That is checkpointing you opted into, not a runtime that owns the loop. Hermes treats checkpointing as the product. Restate treats guaranteed completion as the product. A persisted CrewAI flow will reload state if you wired persistence and the process comes back cleanly. It will not finish a prior-authorization packet because the runtime promised it would. If the listener that calls the crew dies mid-token, you are in the same place LangGraph leaves you: a checkpointer interface and a decision about how much you trust it.
The other leak is the one I named in May and will not pretend 1.15.16 fixed. Hierarchical crews still put a manager model in charge of routing. The manager still invents tasks, still assigns the wrong specialist, still rephrases the request in ways the downstream agent cannot recover from. Flows lets you replace that manager with a function that returns “clinical” or “deny”. That is the move. Teams that adopt Flows and then drop a hierarchical crew into every listener have purchased a state machine so they can keep holding the meeting.
Token cost follows the same line. Role-based handoffs are cheap relative to a group chat because each specialist sees a task, not a transcript. The moment you stuff the prior conversation into every listener “for context,” you have rebuilt AutoGen’s bill inside a nicer graph. Latency shows up first. The auditor shows up second, asking which method made the determination. If the answer is “the reviewer agent, after the manager restated the case,” you do not have a flow. You have a crew with extra decorators.
What 1.15.16 actually shipped is the tell. UUID-backed execution context. The exception type that ended a flow, recorded. Spans that carry the running release. Version 1.15.15, two days earlier, started reporting flow outcome, duration, and human-in-the-loop signals. They are instrumenting the path because the path is what they now have to defend. That is the right work. It is not a substitute for naming the interface before you add the second agent.
The decision rule is the hybrid this week promised.
Use a crew when the output is a draft and the work is actually generative: research synthesis, a first-pass letter, a summary a human will rewrite. Roles earn their keep there because specificity in the system prompt still moves quality, and a sequential pipeline of researcher to writer to reviewer is a pipeline. I have shipped that shape for content review and structured extraction. It works when you can log a string per task and you do not need to prove the path.
Use a flow when the path is the artifact. Eligibility before clinical. Clinical before coding. Coding before the determination letter. Each listener writes structured state. The router is code, not a manager persona. A human-in-the-loop gate sits on the branch an auditor will ask about. If you need a specialist model on one step, call a single agent or a tiny crew inside that listener and take a schema back out. Do not let the crew own the topology.
Skip CrewAI when what you need is a runtime. If the requirement is that this packet finishes even if the box dies on step 37, you want Restate under the graph, or Hermes if the agent is a personal loop that compounds, or Microsoft Agent Framework only if you already live in Azure and you will constrain the graph to Handoff. CrewAI will let you sketch the topology faster than any of those. Sketching is not surviving a restart.
The shared-state problem from May is quieter inside a flow because the state object is first-class. Two listeners read self.state. That is closer to a blackboard than a crew ever got. It is still your job to make that state a schema a validator can reject. A Pydantic model with optional strings is a start. A Pydantic model that will accept a hallucination in the determination field is a chat log with types.
v1.15.3 already gave you @on hooks at execution boundaries. v1.15.10 started collecting skill usage events. The last two patches are almost entirely about knowing how a run died and which release was running when it did. That is what a framework looks like when customers start putting it on packets instead of blog drafts. Take the telemetry. Do not confuse it for guaranteed completion.
Tomorrow I am going to argue the other side of this week’s arc out loud. Multi-agent is the wrong answer more often than the timeline admits. Flows is the concession that makes CrewAI usable in the narrow band where it is not. The rest of the band still wants one agent, better tools, and a checklist.
If you already have crews in production, the next commit is not another backstory. It is the router that replaced the manager.
If this was useful, forward it to one engineer who needs less noise in their feed.


