temporal-ai-agent: a Temporal workflow that runs an LLM agent loop
This demo shows a multi-turn conversation with an AI agent running inside a Temporal workflow.
At a glance
- What is it?
- Temporal's demo repository puts a multi-turn LLM agent inside a Temporal workflow, with native and MCP tools, goals defined per category, and LiteLLM for provider choice. It is a reference implementation, not a library, and the README is explicit about what it has not solved yet.
- Who is it for?
- Adopt this if you are evaluating Temporal as the durability layer under an agent loop and want a working Python reference with goals, signals, queries and Temporal's test framework already wired up. Do not adopt it as a packaged dependency for a production chat product: the README itself says the workflow ID is fixed so only one agent runs at a time, and conversation history is not yet offloaded to external storage.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 172 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem it addresses: an agent loop that survives a crash
A conversational agent is a loop. The model is called, it may ask for a tool, the tool runs, the result goes back to the model, and sometimes a human is asked for input before anything continues. If that loop lives in a request handler, a deploy, a timeout or a process restart in the middle of a tool call leaves you with a half-finished conversation and no record of which step completed. The README states the purpose plainly: the demo shows a multi-turn conversation with an AI agent running inside a Temporal workflow, collecting information towards a goal and running tools along the way. Temporal supplies the durability. The agent logic itself is ordinary Python, which is why the README calls the approach code-first. The target reader is an engineer who already knows what an agent loop looks like and wants to see it expressed as a workflow with activities, signals and queries rather than as a chain of HTTP calls. The README also points at a five minute YouTube walkthrough for the interaction model, which suggests the authors expect people to watch before reading code.
Goals, activities and signals: the moving parts
The unit of work is a goal. Goals live in the /goals/ directory, organised by category: finance, HR, travel, ecommerce and others. A goal bundles the tools the agent may call, and the README describes the agent as operating in single-agent mode by default, focused on one specific goal. There is also an experimental multi-agent mode where the user picks between agent types and switches during a conversation. Tools come in two kinds. Native tools are implemented in the repository under /tools/. MCP tools are reached over the Model Context Protocol from external servers such as Stripe, databases or APIs, and the README notes that the agent acts as an MCP client rather than a server. Model choice is delegated to LiteLLM, so the same workflow can run against OpenAI, Anthropic, Google, Deepseek or a local Ollama model by changing configuration rather than code. The README lists seven elements it considers part of an agentic framework, including an LLM call to check human input for relevance before the real LLM is invoked, and a second LLM call to summarise and compact conversation history. Both of those are design decisions worth noticing: the first adds a model round trip before useful work starts, and the second means history is rewritten rather than appended forever.
Getting it running: two variables, then uv
The README reduces basic configuration to two environment variables. LLM_MODEL is set to a LiteLLM provider string such as openai/gpt-4o, and LLM_KEY holds the matching API key. Beyond that, the setup guide at docs/setup.md covers starting the Temporal Server and the API server, and the README points to shared/mcp_config.py as the place where MCP server configurations are managed. Goal selection is an environment variable too: the README gives AGENT_GOAL=goal_food_ordering together with SHOW_CONFIRM=False as the example that exercises MCP tools against Stripe. Note that SHOW_CONFIRM is described only through that one example, so the full set of values it accepts is not documented in the README itself. Testing uses Temporal's own framework and the uv package manager. The commands given are uv sync to install dependencies including test dependencies, uv run pytest to run everything, and uv run pytest --workflow-environment=time-skipping to run faster by skipping workflow timers. The README claims coverage across workflow tests for signals, queries and state management, activity tests with the LLM integration mocked, and integration tests. That mocking detail matters: the activity tests do not call a real model.
What the README admits is unfinished
The productionalization section is unusually direct, and it is the most useful part of the document. Two constraints stand out. First, conversation history is not offloaded. The README says that in a production setting payload data would need to be stored separately, for example in S3 or a NoSQL database using the claim-check pattern, or otherwise garbage collected, because without that, long conversations fill the workflow's conversation history and begin to breach Temporal event history payload limits. That is a hard ceiling on conversation length in the current code, not a tuning problem. Second, concurrency is capped by workflow identity. A single worker can support many agent workflows at once, but the workflow ID is currently the same on every run, so only one agent runs at a time. The README suggests using a UUID or timestamp per conversation to change that. Both of these are the kind of thing a demo can leave open and a product cannot. A third item is listed as a wish rather than a defect: the UI does not show when an LLM response is being retried after the model produced bad output, so an activity retry is invisible to the person waiting.
Where a plain LangChain or LlamaIndex loop is the better fit
The obvious alternative is a conventional agent framework running in a normal web process, with LangChain or LlamaIndex orchestrating the loop and a database holding message history. That approach is simpler to start and needs no Temporal cluster, no worker deployment and no event history budget. The difference is what happens at the failure boundary. In a request-scoped loop, a crash between the tool call and the model call loses the turn; you reconstruct state from whatever you persisted and hope the tool is idempotent. In this repository the loop is a workflow, so the position in the loop is durable state, and activities can be retried under Temporal's policy. The cost is operational: you now run Temporal Server, a worker and the API server, and you inherit event history limits, which is exactly the constraint the README flags. Choose the framework route when conversations are short, tools are cheap to repeat, and nobody minds a dropped turn. Choose this pattern when a goal spans many turns, tools touch external systems with side effects such as payments, and a lost turn is a support ticket.
Licence and the cost of tracking main
The repository is MIT licensed, which permits commercial use and modification provided the licence text is retained. This is not legal advice; read the LICENSE file and your own counsel's view before shipping. On maintenance, the release history shows 0.4.0 and 0.4.1 in June 2025, and the last push to main is dated 2026-03-27, so the project is still receiving commits even though no release has been cut since 0.4.1. That gap between releases and commits is itself information: if you vendor the code you are tracking main, not a tagged version. The README points to docs/todo.md for work the maintainers want done, and to docs/adding-goals-and-tools.md for extension, so the intended upgrade path is to keep your goals and tools in the directories the project already defines and rebase them. The dependency surface is LiteLLM, the MCP client libraries and Temporal's Python SDK, and LiteLLM's provider list moves quickly, so pinning LLM_MODEL to a specific provider string is safer than relying on a default. There is also an enablement guide and slide deck listed as internal Temporal employee resources, which tells you the primary audience the authors had in mind.
Editorial conclusion
Adopt this if you are evaluating Temporal as the durability layer under an agent loop and want a working Python reference with goals, signals, queries and Temporal's test framework already wired up. Do not adopt it as a packaged dependency for a production chat product: the README itself says the workflow ID is fixed so only one agent runs at a time, and conversation history is not yet offloaded to external storage. Before you commit, read docs/architecture-decisions.md, confirm the AGENT_GOAL value and goal directory you need exists under /goals/, and check whether the MCP server you intend to call is already described in shared/mcp_config.py.
Community notes