Quickstart
Run your first agent, watch it work, give it a tool of your own, and use the SDK API.
1 min read
In five minutes you will run an agent, stream what it does, add a tool of your own, and run the same agent through the async SDK API.
1. Install and set a key
pip install 'shipit-agent[anthropic]'
export SHIPIT_LLM_PROVIDER=anthropic
export ANTHROPIC_API_KEY=sk-ant-...Any provider works; Configure a model lists them.
2. Run an agent
from shipit_agent import Agent
from shipit_agent.llms import build_llm_from_env
agent = Agent.with_builtins(llm=build_llm_from_env(), project_root=".")
result = agent.run("Find the TODO comments in this project and group them by file.")
print(result.output)Agent.with_builtins() gives the agent the built-in tools: reading and searching files, editing, bash, the web, a todo list, sub-agents and more. project_root is the folder the file tools and bash work in; they refuse paths outside it.
result is an AgentResult. Besides output, it has every message, every event and every tool result. result.metadata["usage"] holds the token counts, and result.metadata["run_summary"] how the run went, including estimated_cost_usd.
3. Watch it work
stream() runs the same loop and yields events as they happen:
for event in agent.stream("Find the TODO comments in this project."):
print(f"{event.type:22} {event.message}")run_started Agent run started
step_started LLM completion started
assistant_message Model response
tool_called Tool called: grep_files
tool_completed Tool completed: grep_files
step_started LLM completion started
assistant_message Model response
final_answer Final answer generated
run_summary Run finished: 2 iterations, 1 tool calls
run_completed Agent run completedEach event has a type, a message and a payload with the details: the tool's arguments, its output, token counts. text_delta events carry the answer as it is written. Streaming covers them all.
4. Give it your own tool
Any function becomes a tool. Its name, docstring and type hints become the schema the model sees.
from shipit_agent import Agent
from shipit_agent.llms import build_llm_from_env
from shipit_agent.tools import FunctionTool
def order_status(order_id: str) -> str:
"""Look up an order's shipping status by its id."""
return f"{order_id}: shipped on 3 November, tracking ZX-9917"
agent = Agent(
llm=build_llm_from_env(),
tools=[FunctionTool.from_callable(order_status, read_only=True)],
)
print(agent.run("Where is order A-1043?").output)read_only=True tells the permission system the tool changes nothing, so it never needs approval. Custom tools covers tool classes, rich output and errors.
5. The same agent, through the SDK API
The SDK API is the async way in. query() yields typed messages and ends with a ResultMessage.
import asyncio
from shipit_agent.sdk import AgentOptions, AssistantMessage, ResultMessage, TextBlock, query
async def main() -> None:
options = AgentOptions(
model="claude-sonnet-5-5",
cwd=".",
permission_mode="acceptEdits",
max_turns=20,
)
async for message in query(prompt="Fix the failing test in tests/", options=options):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
elif isinstance(message, ResultMessage):
print(message.subtype, message.num_turns, "turns", f"${message.total_cost_usd:.4f}")
asyncio.run(main())permission_mode="acceptEdits" lets the agent edit files without asking; commands that delete files, push or reach outside the project still need approval. Permissions explains the modes.
Next
- Core concepts: how the loop, tools, permissions and context fit together.
- Tools: what each built-in tool does.
- Agent SDK API: every option and message.
- Examples: complete agents to copy.