Create your first Agent ======================= Goal: create a Provider-backed **Agent**, attach instructions and tools, and run a simple smoke test with the **real** APIs in this repository. Prerequisites ------------- * Stack up (:doc:`../quickstart`) * Session cookie or token for an authenticated user * A **Provider** with at least one **Model**. Boot seeds Ollama (synced from tags when reachable), OpenAI with ``gpt-4o-mini`` / ``gpt-4o``, and FAL. OpenAI chat needs ``OPENAI_API_KEY`` in the host ``.env`` (Compose already injects it). Sync is Ollama tags or OpenAI ``GET /v1/models``; FAL has no catalog — add rows by API id. What you need ------------- +---------------+--------------------------------------------------+ | Object | Role | +===============+==================================================+ | Provider | Inference backend (kind, URL, api_key_env name) | +---------------+--------------------------------------------------+ | Model | LLM row under a Provider (``Agent.model`` FK) | +---------------+--------------------------------------------------+ | Tool | Catalog row: ``id`` + ``definition`` import path | +---------------+--------------------------------------------------+ | Agent | ``model`` + ``instructions`` + M2M ``tools`` | +---------------+--------------------------------------------------+ Create or reuse a Model ----------------------- List providers and models:: GET /api/provider/ GET /api/model/ Or sync a provider catalog into local ``Model`` rows (Ollama tags, OpenAI ``/v1/models``):: POST /api/provider//sync/ Django shell:: from agency.models import Provider, Model provider = Provider.objects.filter(name="openai").first() model = provider.models.filter(name="gpt-4o-mini").first() Create an Agent --------------- REST (field names from ``AgentSerializer``):: POST /api/agent/ Content-Type: application/json { "name": "Researcher", "instructions": "You are a careful research assistant. Be concise.", "model_id": "", "tool_ids": ["get_datetime"], "deep": false } * ``model_id`` — PK of ``Model`` * ``tool_ids`` — PKs of ``Tool`` (usually the export attribute name, e.g. ``get_datetime``; ``definition`` is the import path ``agency.tools.basic.get_datetime``) * ``tools`` in responses is read-only nested detail Python:: from agency.models import Agent, Model, Tool model = Model.objects.get(id="...") agent = Agent.objects.create( name="Researcher", model=model, instructions="You are a careful research assistant. Be concise.", ) tool = Tool.objects.get(id="get_datetime") # if seeded via ensure_default_tools agent.tools.add(tool) Smoke test (no Execution lifecycle) ----------------------------------- ``Agent.test`` builds a one-shot LangGraph invoke with the agent's model and tools. It does **not** create Execution, Thread, Run, or Checkpoint:: POST /api/agent//test/ Content-Type: application/json {"message": "What time is it?"} Python:: output = agent.test("What time is it?") # LangGraph-style dict with "messages", … Use this to verify model connectivity and tool wiring. For product runs that must be auditable and resumable, use a **Mission** dispatch instead (:doc:`first-mission`). What persists / what does not ----------------------------- +---------------------------+------------------------------------------+ | Path | Persisted | +===========================+==========================================+ | Creating Agent / tools | Agent, Tool M2M, Model FK | +---------------------------+------------------------------------------+ | ``Agent.test`` / test API | **Nothing** in Execution/Thread/Run | +---------------------------+------------------------------------------+ | ``Mission.dispatch`` / | Execution, Thread, Run, checkpoints, … | | ``Agent.execute`` | (see next tutorials) | +---------------------------+------------------------------------------+ Possible improvements (not implemented) --------------------------------------- * Skills exist as a model but are **not** wired to ``Agent`` (no M2M yet). * ``Agent.test`` and product execute share tools/model but diverge on persistence — easy to confuse; keep them separate in ops docs. Next: :doc:`first-mission`.