{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "intro",
      "metadata": {},
      "source": [
        "# Run an Agent\n",
        "\n",
        "This notebook shows the smallest useful Everruns SDK flow: create an agent, start a Generic harness session, send one message, and stream the reply inline.\n",
        "\n",
        "It defaults to `https://app.everruns.com/api`. Override `EVERRUNS_API_URL` only when you want to point the same notebook at a local or self-hosted Everruns deployment."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "install-section",
      "metadata": {},
      "source": [
        "## Install the SDK\n",
        "\n",
        "Run this cell once in the notebook environment."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "install-sdk",
      "metadata": {},
      "outputs": [],
      "source": [
        "%pip install -q everruns-sdk"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "configure-section",
      "metadata": {},
      "source": [
        "## Configure the client\n",
        "\n",
        "Set `EVERRUNS_API_KEY` before running against `app.everruns.com`. For local dev mode you can point `EVERRUNS_API_URL` at your local server and use `dev` as the key."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "configure-client",
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "import uuid\n",
        "\n",
        "from everruns_sdk import Everruns\n",
        "\n",
        "BASE_URL = os.environ.get(\"EVERRUNS_API_URL\", \"https://app.everruns.com/api\")\n",
        "API_KEY = os.environ.get(\"EVERRUNS_API_KEY\", \"\")\n",
        "if BASE_URL.startswith(\"https://app.everruns.com\") and not API_KEY:\n",
        "    raise RuntimeError(\"Set EVERRUNS_API_KEY before running this notebook against app.everruns.com.\")\n",
        "\n",
        "if not API_KEY:\n",
        "    API_KEY = \"dev\"\n",
        "\n",
        "client = Everruns(api_key=API_KEY, base_url=BASE_URL)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "create-agent-section",
      "metadata": {},
      "source": [
        "## Create the agent\n",
        "\n",
        "This uses the server's default model. The unique suffix keeps the notebook rerunnable."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "create-agent",
      "metadata": {},
      "outputs": [],
      "source": [
        "run_suffix = uuid.uuid4().hex[:8]\n",
        "\n",
        "agent = await client.agents.create(\n",
        "    name=f\"sdk-notebook-{run_suffix}\",\n",
        "    system_prompt=(\n",
        "        \"You are a concise demo assistant. \"\n",
        "        \"Answer in short bullet points and keep responses short.\"\n",
        "    ),\n",
        ")\n",
        "\n",
        "agent.id"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "start-session-section",
      "metadata": {},
      "source": [
        "## Start a session\n",
        "\n",
        "A Generic harness session is the quickest way to run the agent without adding extra capabilities or files."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "start-session",
      "metadata": {},
      "outputs": [],
      "source": [
        "session = await client.sessions.create(\n",
        "    harness_name=\"generic\",\n",
        "    agent_id=agent.id,\n",
        "    title=f\"SDK notebook demo {run_suffix}\",\n",
        ")\n",
        "\n",
        "session.id"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "send-message-section",
      "metadata": {},
      "source": [
        "## Send a message and stream the reply\n",
        "\n",
        "This cell sends one message, prints the streamed text as it arrives, and returns a small result object with the IDs you might want to keep."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "send-message",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "- Everruns runs durable agent workflows behind a stable API and session model.\n",
            "- It keeps agent state, tool execution, and event streams together so retries stay predictable.\n",
            "- Product teams use it when they want streaming, durable agents without rebuilding the control plane themselves.\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "{'base_url': 'https://app.everruns.com/api',\n",
              " 'agent_id': 'agent_0196831a1f9c7a0f8a5c9ab3d7d0f201',\n",
              " 'session_id': 'session_0196831a20837ddbb05fd8f6d0c8f64a',\n",
              " 'response': '- Everruns runs durable agent workflows behind a stable API and session model.\\n- It keeps agent state, tool execution, and event streams together so retries stay predictable.\\n- Product teams use it when they want streaming, durable agents without rebuilding the control plane themselves.'}"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "await client.messages.create(\n",
        "    session.id,\n",
        "    \"What does Everruns do, and why would a product team use it?\",\n",
        ")\n",
        "\n",
        "streamed_chunks = []\n",
        "completed_text = None\n",
        "\n",
        "async for event in client.events.stream(session.id):\n",
        "    if event.type == \"output.message.delta\":\n",
        "        delta = event.data.get(\"delta\", \"\")\n",
        "        streamed_chunks.append(delta)\n",
        "        print(delta, end=\"\", flush=True)\n",
        "    elif event.type == \"output.message.completed\":\n",
        "        message = event.data.get(\"message\", {})\n",
        "        completed_text = \"\\n\".join(\n",
        "            part.get(\"text\", \"\")\n",
        "            for part in message.get(\"content\", [])\n",
        "            if part.get(\"type\") == \"text\"\n",
        "        ).strip()\n",
        "    elif event.type == \"turn.completed\":\n",
        "        break\n",
        "    elif event.type == \"turn.failed\":\n",
        "        raise RuntimeError(event.data.get(\"error\", \"turn failed\"))\n",
        "\n",
        "result = {\n",
        "    \"base_url\": BASE_URL,\n",
        "    \"agent_id\": agent.id,\n",
        "    \"session_id\": session.id,\n",
        "    \"response\": \"\".join(streamed_chunks).strip() or completed_text or \"\",\n",
        "}\n",
        "\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "next-steps",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "- Change the prompt and rerun the last three cells\n",
        "- Swap the message text for your own task\n",
        "- Move the same flow into a script or service once the notebook feels right"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.12"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
