Inputs: one crew, many tickets
Inputs are the values kickoff fills into a task's placeholders, so one crew answers any ticket.
Last updated: 28 Sep, 2026 · CrewAI 1.15
The agent-prompt lesson showed the task's text becoming the user message. The first-crew lesson's task had the question typed into it; a support desk needs the same crew for every ticket, so the question becomes a placeholder.
View the code here
import os
import re
from crewai import BaseLLM
os.environ["CREWAI_DISABLE_TELEMETRY"] = "true"
os.environ["CREWAI_TRACING_ENABLED"] = "false"
os.environ["CREWAI_DISABLE_VERSION_CHECK"] = "true"
class ShopLLM(BaseLLM):
def call(self, messages, tools=None, **kwargs):
if isinstance(messages, str):
messages = [{"role": "user", "content": messages}]
text = messages[-1]["content"]
orders = re.findall(r"\b[A-Z]\d+\b", text)
if orders:
return f"I have no way to look up {orders[0]} yet."
return "Hello. Which order is this about?"
A task with a placeholder
from crewai import Agent, Crew, Task
from shop_llm import ShopLLM
agent = Agent(
role="Support agent",
goal="Answer customers of a small online shop",
backstory="You have worked the shop's support desk for years.",
llm=ShopLLM(model="shop"),
)
task = Task(
description="Answer the customer: {question}",
expected_output="One short, friendly sentence.",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])The description now contains {question}, a placeholder in curly braces. The agent is the one from the first-crew lesson.
Filling the placeholder
result = crew.kickoff(inputs={"question": "Where is my order A17?"})
print(result.raw)I have no way to look up A17 yet.
inputs is a dictionary. Before the crew runs, CrewAI puts each value in place of the placeholder with the same name, in task descriptions, expected outputs and the agent's role, goal and backstory.
Reporting a missing placeholder
crew.kickoff(inputs={"q": "Where is my order A17?"})KeyError: "Template variable 'question' not found in inputs dictionary"
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "main.py", line 1, in <module>
crew.kickoff(inputs={"q": "Where is my order A17?"})
ValueError: Missing required template variable 'Template variable 'question' not found in inputs dictionary' in descriptionA placeholder with no value in inputs stops the run before any model is called, and the error names the missing variable. Calling kickoff() with no inputs at all is different: nothing is filled in, and the agent is asked about the literal text {question}.
Running many tickets
tickets = [
{"question": "Where is my order A17?"},
{"question": "Hello, can you help me?"},
]
for result in crew.kickoff_for_each(inputs=tickets):
print(result.raw)I have no way to look up A17 yet. Hello. Which order is this about?
kickoff_for_each runs the crew once per dictionary and returns the results in the same order. The first ticket names an order; the second does not, so the model asks which one.
Reading the two runs
- inputs is a dictionary; each value replaces the placeholder of the same name before the crew runs.
- A missing name stops the run early, naming the variable, before any model is called.
- kickoff_for_each runs once per ticket and returns the results in the same order.
kickoff vs kickoff_for_each
| Method | Runs | Returns |
|---|---|---|
| kickoff(inputs=...) | once | one CrewOutput |
| kickoff_for_each(inputs=[...]) | once per dictionary | a list of CrewOutputs |
When placeholders pay off
- One crew has to answer many tickets that differ only in their text.
- You run a batch of inputs and want each result kept separate.
- The same value belongs in more than one field, such as the goal and the task.
Related
- Previous: The agent prompt: what the model is sent
- Next: Watching a crew work
- Put
{question}in the agent's goal as well and run the first example. - Add a third ticket about C40 to the list.
- Call
crew.kickoff()with no inputs, then printtask.description.
Little by little, you're building something great.