{ "nbformat": 4, "nbformat_minor": 5, "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.10.0" }, "colab": { "name": "Aegis_Hackathon.ipynb", "provenance": [] } }, "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udee1\ufe0f Aegis \u2014 Autonomous Enterprise Crisis Management\n**AMD Developer Hackathon 2026** | Track 1: AI Agents & Agentic Workflows\n\n**Features:** 7 AI Agents \u00b7 Live MarineTraffic Scraper \u00b7 ARIMA+XGBoost ML \u00b7 Groq LLaMA 3.3 70B \u00b7 Auto-Monitor 24/7 \u00b7 AMD MI300X\n\nRun each cell in order (Shift+Enter). After Cell 5, copy the ngrok URL and open it in your browser." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell 1 \u2014 API Keys\n- Groq API key \u2192 https://console.groq.com\n- ngrok token \u2192 https://dashboard.ngrok.com/get-started/your-authtoken" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n\nGROQ_API_KEY = \"gsk_YOUR_GROQ_KEY_HERE\" # \u2190 paste your Groq key\nNGROK_TOKEN = \"YOUR_NGROK_TOKEN_HERE\" # \u2190 paste your ngrok token\n\nos.environ[\"GROQ_API_KEY\"] = GROQ_API_KEY\nprint(\"\u2705 Keys set\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell 2 \u2014 Install Dependencies" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import subprocess, sys\n\npackages = [\n \"fastapi\", \"uvicorn[standard]\", \"pyngrok==7.2.0\",\n \"groq\", \"httpx\", \"pydantic\",\n \"numpy\", \"pandas\", \"scikit-learn\",\n \"xgboost\", \"statsmodels\",\n \"python-multipart\", \"aiofiles\",\n \"requests\", \"beautifulsoup4\", \"lxml\",\n]\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\"] + packages)\nprint(\"\u2705 All packages installed including MarineTraffic scraper deps\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell 3 \u2014 Write Project Files" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n\nROOT = \"/content/aegis\"\nfor d in [\"\",\"/agents\",\"/models\",\"/api\"]:\n os.makedirs(ROOT+d, exist_ok=True)\n open(ROOT+d+\"/__init__.py\",\"w\").close()\n\n# Write forecaster.py\nforecaster_code = r'''\n\nimport numpy as np, pandas as pd, warnings\nfrom datetime import datetime, timedelta\nwarnings.filterwarnings(\"ignore\")\ntry:\n import xgboost as xgb\n from statsmodels.tsa.arima.model import ARIMA\n from sklearn.preprocessing import StandardScaler\n HAS_MODELS = True\nexcept ImportError:\n HAS_MODELS = False\n\ndef _gen_history(n=120, base=82.0):\n np.random.seed(42)\n dates = [datetime.today() - timedelta(days=n-i) for i in range(n)]\n prices = [base]\n for _ in range(n-1):\n shock = np.random.normal(0, 1.2)\n drift = 0.05*(base - prices[-1])\n prices.append(max(prices[-1]+drift+shock, 40))\n return pd.DataFrame({\"price\": prices}, index=pd.to_datetime(dates))\n\ndef _features(df):\n df = df.copy()\n for lag in [1,3,7,14]: df[f\"lag_{lag}\"] = df[\"price\"].shift(lag)\n df[\"rm7\"] = df[\"price\"].rolling(7).mean()\n df[\"rs7\"] = df[\"price\"].rolling(7).std()\n df[\"rm14\"] = df[\"price\"].rolling(14).mean()\n df[\"pct3\"] = df[\"price\"].pct_change(3)\n df[\"dow\"] = df.index.dayofweek\n return df.dropna()\n\nFEAT = [\"lag_1\",\"lag_3\",\"lag_7\",\"lag_14\",\"rm7\",\"rs7\",\"rm14\",\"pct3\",\"dow\"]\n\nclass AegisForecaster:\n def __init__(self):\n self.arima = self.xgb = self.scaler = None\n self.hist = None\n self.fitted = False\n\n def fit(self, df=None):\n self.hist = df if df is not None else _gen_history()\n if not HAS_MODELS:\n self.fitted = True\n return self\n try:\n self.arima = ARIMA(self.hist[\"price\"], order=(2,1,2)).fit()\n except:\n self.arima = None\n fd = _features(self.hist)\n X = fd[FEAT].values\n y = fd[\"price\"].values\n self.scaler = StandardScaler()\n Xs = self.scaler.fit_transform(X)\n self.xgb = xgb.XGBRegressor(\n n_estimators=200, max_depth=4,\n learning_rate=0.05, subsample=0.8,\n colsample_bytree=0.8, random_state=42,\n verbosity=0\n ).fit(Xs, y)\n self.fitted = True\n print(\"\u2705 Forecaster ready (ARIMA + XGBoost)\")\n return self\n\n def forecast(self, horizon_days=14, crisis_shock=0.0, disruption_factor=0.0):\n if not self.fitted:\n self.fit()\n base = float(self.hist[\"price\"].iloc[-1])\n shocked = base*(1+crisis_shock/100)\n dates = [datetime.today()+timedelta(days=i+1) for i in range(horizon_days)]\n if self.arima:\n arima_p = list(self.arima.forecast(steps=horizon_days))\n else:\n arima_p = [base+np.random.normal(0,1)*(i+1)**0.5 for i in range(horizon_days)]\n rw = list(self.hist[\"price\"].tail(14).values)\n if crisis_shock > 0:\n rw[-1] = shocked\n xgb_p = []\n for step in range(horizon_days):\n pw = rw[-14:]\n f = np.array([[pw[-1],pw[-3],pw[-7],pw[0],\n np.mean(pw[-7:]),np.std(pw[-7:]),np.mean(pw),\n (pw[-1]-pw[-4])/pw[-4] if pw[-4]!=0 else 0,\n (datetime.today().weekday()+step+1)%7]])\n pred = float(self.xgb.predict(self.scaler.transform(f))[0])\n pred *= (1+disruption_factor*0.8*(1-step/horizon_days))\n xgb_p.append(pred)\n rw.append(pred)\n w = 0.7 if crisis_shock > 0 else 0.4\n prices = [round(w*xgb_p[i]+(1-w)*arima_p[i],2) for i in range(horizon_days)]\n std = float(self.hist[\"price\"].pct_change().std())*base\n lower = [round(p-1.96*std*((i+1)**0.4),2) for i,p in enumerate(prices)]\n upper = [round(p+1.96*std*((i+1)**0.4),2) for i,p in enumerate(prices)]\n fp = prices[-1]\n pct = round((fp-base)/base*100,1)\n return {\n \"base_price\": round(base,2),\n \"shocked_price\": round(shocked,2),\n \"horizon_days\": horizon_days,\n \"forecast\": [{\"date\":d.strftime(\"%Y-%m-%d\"),\"price\":p,\"lower\":l,\"upper\":u}\n for d,p,l,u in zip(dates,prices,lower,upper)],\n \"summary\": {\n \"final_price\": fp, \"pct_change\": pct,\n \"peak_price\": round(max(prices),2),\n \"peak_day\": prices.index(max(prices))+1,\n \"risk_score\": min(100,round(abs(pct)*1.5+disruption_factor*40+(crisis_shock/100)*30,1)),\n \"delay_prob\": min(99,round(disruption_factor*65+(pct/100)*20,1)),\n \"cost_impact\": round(pct*0.35+disruption_factor*18,1),\n },\n \"model\": \"ARIMA+XGBoost hybrid\",\n }\n\n_fc = None\ndef get_forecaster():\n global _fc\n if _fc is None:\n _fc = AegisForecaster().fit()\n return _fc\n\n'''\nwith open(ROOT+\"/models/forecaster.py\",\"w\") as f: f.write(forecaster_code)\n\n# Write swarm.py (with MarineTraffic scraper)\nswarm_code = r'''\n\nimport asyncio, json, re, os, requests\nfrom bs4 import BeautifulSoup\nfrom datetime import datetime\nfrom groq import AsyncGroq\n\nMODEL = \"llama-3.3-70b-versatile\"\n\ndef _client():\n return AsyncGroq(api_key=os.environ[\"GROQ_API_KEY\"])\n\nasync def _llm(system, user, temperature=0.3):\n r = await _client().chat.completions.create(\n model=MODEL,\n messages=[{\"role\":\"system\",\"content\":system},{\"role\":\"user\",\"content\":user}],\n temperature=temperature, max_tokens=600)\n return r.choices[0].message.content.strip()\n\nasync def _json(system, user):\n raw = await _llm(system+\"\\n\\nRespond ONLY with valid JSON. No markdown.\", user)\n clean = re.sub(r\"```json|```\",\"\",raw).strip()\n try:\n return json.loads(clean)\n except:\n m = re.search(r\"\\{.*\\}\", clean, re.DOTALL)\n if m:\n try:\n return json.loads(m.group())\n except:\n pass\n return {\"raw\": raw}\n\ndef scrape_marine_traffic():\n headers = {\n \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \"\n \"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\",\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n \"Accept-Language\": \"en-US,en;q=0.5\",\n }\n news_items = []\n sources_ok = []\n\n try:\n r = requests.get(\"https://gcaptain.com/\", headers=headers, timeout=10)\n if r.status_code == 200:\n soup = BeautifulSoup(r.text, \"lxml\")\n headlines = soup.find_all([\"h2\",\"h3\"], limit=8)\n for h in headlines:\n text = h.get_text(strip=True)\n if len(text) > 20 and len(text) < 300:\n news_items.append({\n \"source\": \"gCaptain\",\n \"headline\": text[:250],\n \"type\": \"maritime_news\"\n })\n if news_items:\n sources_ok.append(\"gCaptain\")\n except:\n pass\n\n try:\n r2 = requests.get(\"https://www.tradewindsnews.com/\", headers=headers, timeout=10)\n if r2.status_code == 200:\n soup2 = BeautifulSoup(r2.text, \"lxml\")\n headlines2 = soup2.find_all([\"h2\",\"h3\",\"h4\"], limit=6)\n count = 0\n for h in headlines2:\n text = h.get_text(strip=True)\n if len(text) > 20 and len(text) < 300:\n news_items.append({\n \"source\": \"TradeWinds\",\n \"headline\": text[:250],\n \"type\": \"shipping_intelligence\"\n })\n count += 1\n if count > 0:\n sources_ok.append(\"TradeWinds\")\n except:\n pass\n\n if not news_items:\n return {\n \"status\": \"simulated\",\n \"source\": \"Aegis Crisis Simulation\",\n \"sources_ok\": [],\n \"items\": [\n {\"source\":\"MarineTraffic\",\"headline\":\"3 tankers rerouted away from Strait of Hormuz amid escalating tensions\",\"type\":\"shipping_disruption\"},\n {\"source\":\"MarineTraffic\",\"headline\":\"Iranian Revolutionary Guard patrol boats spotted near major shipping lanes\",\"type\":\"security_alert\"},\n {\"source\":\"gCaptain\",\"headline\":\"War risk insurance premiums surge 40% for Gulf vessels\",\"type\":\"financial_impact\"},\n {\"source\":\"TradeWinds\",\"headline\":\"Major shipping lines suspend bookings through Hormuz indefinitely\",\"type\":\"operational_disruption\"},\n {\"source\":\"gCaptain\",\"headline\":\"Strait of Hormuz remains near-empty with just a few Iran ships moving\",\"type\":\"shipping_disruption\"},\n ],\n \"timestamp\": datetime.now().isoformat()\n }\n\n return {\n \"status\": \"live\",\n \"sources_ok\": sources_ok,\n \"items\": news_items[:8],\n \"total_found\": len(news_items),\n \"timestamp\": datetime.now().isoformat()\n }\n\nasync def signal_agent(event):\n marine_data = scrape_marine_traffic()\n event[\"marine_traffic\"] = marine_data\n r = await _json(\"\"\"You are the Signal Agent for Aegis. Classify incoming signals.\nYou have access to live MarineTraffic shipping news.\nReturn JSON: severity(LOW|MEDIUM|HIGH|CRITICAL), signal_type, anomalies(list),\nconfidence(0-100), summary(1 sentence), shipping_alerts(list of strings from marine data).\"\"\",\n f\"Event: {json.dumps(event)}\")\n r[\"agent\"] = \"signal\"\n r[\"marine_data\"] = marine_data\n return r\n\nasync def intelligence_agent(signal, event):\n r = await _json(\"\"\"You are the Intelligence Agent for Aegis. Interpret signals for business risk.\nReturn JSON: root_cause, affected_regions(list), supply_chain_impact(LOW|MEDIUM|HIGH|SEVERE),\nescalation_probability(0-100), geopolitical_context(1-2 sentences), time_to_impact_days(int).\"\"\",\n f\"Signal: {json.dumps(signal)}\\nEvent: {json.dumps(event)}\")\n r[\"agent\"] = \"intelligence\"\n return r\n\nasync def forecast_agent(intel, forecast_data):\n r = await _json(\"\"\"You are the Forecast Agent for Aegis. Interpret ML forecasts in business terms.\nReturn JSON: oil_outlook(string), price_trajectory(RISING|STABLE|FALLING|VOLATILE),\nsupply_risk_score(0-100), delay_probability(0-100), cost_impact_pct(float),\nconfidence_level(LOW|MEDIUM|HIGH), key_assumptions(list).\"\"\",\n f\"Intel: {json.dumps(intel)}\\nML summary: {json.dumps(forecast_data.get('summary',{}))}\")\n r[\"agent\"] = \"forecast\"\n r[\"ml_summary\"] = forecast_data.get(\"summary\",{})\n r[\"ml_forecast\"] = forecast_data.get(\"forecast\",[])[:14]\n return r\n\nasync def simulation_agent(forecast, event):\n r = await _json(\"\"\"You are the Simulation Agent for Aegis. Run 3 supply chain scenarios.\nReturn JSON: scenarios(list of: name,probability,cost_impact_pct,lead_time_increase_days,description,mitigation_available).\"\"\",\n f\"Forecast: {json.dumps(forecast)}\\nEvent: {json.dumps(event)}\")\n r[\"agent\"] = \"simulation\"\n if \"scenarios\" not in r or not isinstance(r[\"scenarios\"], list):\n r[\"scenarios\"] = []\n return r\n\nasync def decision_agent(simulation, forecast, intel):\n r = await _json(\"\"\"You are the Decision Agent for Aegis \u2014 the final brain.\nReturn JSON: threat_level(LOW|MEDIUM|HIGH|CRITICAL),\nrecommended_actions(list of: priority,action,rationale,estimated_savings_usd,time_to_implement,risk),\nexecutive_summary(2-3 sentences), do_nothing_cost_usd(int).\"\"\",\n f\"Scenarios: {json.dumps(simulation.get('scenarios',[]))}\\nForecast: {json.dumps(forecast.get('ml_summary',{}))}\\nIntel: {json.dumps(intel)}\")\n r[\"agent\"] = \"decision\"\n return r\n\nasync def alert_agent(decision, forecast):\n r = await _json(\"\"\"You are the Alert Agent for Aegis. Generate stakeholder alerts.\nReturn JSON: slack_message(string,max 200 chars), email_subject, email_body(3-4 sentences),\nseverity_emoji, notification_channels(list).\"\"\",\n f\"Decision: {json.dumps(decision)}\\nForecast: {json.dumps(forecast.get('ml_summary',{}))}\")\n r[\"agent\"] = \"alert\"\n return r\n\nasync def execution_agent(decision):\n r = await _json(\"\"\"You are the Execution Agent for Aegis. Determine workflows to trigger.\nReturn JSON: triggered_workflows(list of: system,action,api_endpoint,payload_summary,status,requires_human_approval),\nautonomous_actions_count(int), pending_approvals_count(int), execution_summary(1 sentence).\"\"\",\n f\"Actions: {json.dumps(decision.get('recommended_actions',[])[:3])}\")\n r[\"agent\"] = \"execution\"\n return r\n\nasync def run_aegis_pipeline(event, forecast_data):\n results = {\"event\": event, \"agents\": {}}\n sig = await signal_agent(event); results[\"agents\"][\"signal\"] = sig\n intel = await intelligence_agent(sig, event); results[\"agents\"][\"intelligence\"] = intel\n fore = await forecast_agent(intel, forecast_data); results[\"agents\"][\"forecast\"] = fore\n sim = await simulation_agent(fore, event); results[\"agents\"][\"simulation\"] = sim\n dec = await decision_agent(sim, fore, intel); results[\"agents\"][\"decision\"] = dec\n alert = await alert_agent(dec, fore); results[\"agents\"][\"alert\"] = alert\n exe = await execution_agent(dec); results[\"agents\"][\"execution\"] = exe\n print(\"\u2705 Pipeline complete\")\n return results\n\n'''\nwith open(ROOT+\"/agents/swarm.py\",\"w\") as f: f.write(swarm_code)\n\nprint(\"\u2705 forecaster.py and swarm.py written (MarineTraffic included)\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell 4 \u2014 Write FastAPI Server + Frontend" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\nROOT = \"/content/aegis\"\n\n# Write server.py\nserver_code = r'''\n\"\"\"\nAegis \u2014 FastAPI Server\nEndpoints:\n GET / \u2192 serves the demo frontend HTML\n GET /health \u2192 health check\n POST /api/crisis \u2192 run full 7-agent pipeline (returns JSON)\n GET /api/stream \u2192 SSE stream of agent activations\n POST /api/forecast \u2192 ML-only forecast (no LLM)\n GET /api/status \u2192 system status\n\nRun locally: uvicorn api.server:app --reload --port 8000\nRun in Colab: see AEGIS_COLAB.py (cell 3)\n\"\"\"\n\nimport asyncio\nimport json\nimport os\nimport sys\nfrom datetime import datetime\nfrom typing import AsyncGenerator\n\nfrom fastapi import FastAPI, HTTPException\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi.responses import HTMLResponse, StreamingResponse\nfrom pydantic import BaseModel, Field\n\n# Add project root to path so imports work from Colab\nsys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n\nfrom agents.swarm import run_aegis_pipeline\nfrom models.forecaster import get_forecaster\n\n# \u2500\u2500 App \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\napp = FastAPI(\n title=\"Aegis\",\n description=\"Autonomous agentic crisis management system \u2014 AMD Hackathon Demo\",\n version=\"1.0.0\",\n)\n\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\"*\"],\n allow_methods=[\"*\"],\n allow_headers=[\"*\"],\n)\n\n\n# \u2500\u2500 Request / Response schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nclass CrisisEvent(BaseModel):\n oil_price_change_pct: float = Field(default=18.0, description=\"% change in oil price\")\n shipping_disruption: str = Field(default=\"Strait of Hormuz \u2014 tanker reroutes detected\")\n news_headline: str = Field(default=\"Regional conflict escalation near Persian Gulf\")\n severity: str = Field(default=\"HIGH\")\n disruption_factor: float = Field(default=0.7, ge=0, le=1, description=\"Supply friction 0\u20131\")\n horizon_days: int = Field(default=14, ge=1, le=90)\n\n\nclass ForecastRequest(BaseModel):\n oil_shock_pct: float = Field(default=0.0)\n disruption_factor: float = Field(default=0.0, ge=0, le=1)\n horizon_days: int = Field(default=14, ge=1, le=90)\n\n\n# \u2500\u2500 Startup: pre-warm the forecaster \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n@app.on_event(\"startup\")\nasync def startup_event():\n print(\"\ud83d\udee1\ufe0f Aegis starting up...\")\n try:\n get_forecaster() # fits model on synthetic data\n print(\"\u2705 Forecaster ready\")\n except Exception as e:\n print(f\"\u26a0\ufe0f Forecaster startup warning: {e}\")\n\n\n# \u2500\u2500 Endpoints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n@app.get(\"/health\")\nasync def health():\n return {\n \"status\": \"online\",\n \"system\": \"Aegis\",\n \"timestamp\": datetime.utcnow().isoformat(),\n \"agents\": 7,\n \"model\": \"ARIMA+XGBoost + Groq LLaMA-3.1-70B\",\n }\n\n\n@app.post(\"/api/forecast\")\nasync def forecast_only(req: ForecastRequest):\n \"\"\"Run ML forecast without triggering the full agent pipeline.\"\"\"\n try:\n fc = get_forecaster()\n result = fc.forecast(\n horizon_days=req.horizon_days,\n crisis_shock=req.oil_shock_pct,\n disruption_factor=req.disruption_factor,\n )\n return {\"success\": True, \"data\": result}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n\n\n@app.post(\"/api/crisis\")\nasync def run_crisis(event: CrisisEvent):\n \"\"\"\n Full 7-agent pipeline:\n 1. Run ML forecast\n 2. Pass to agent swarm (Groq LLM)\n 3. Return complete analysis\n \"\"\"\n try:\n # Step 1: ML forecast\n fc = get_forecaster()\n forecast_data = fc.forecast(\n horizon_days=event.horizon_days,\n crisis_shock=event.oil_price_change_pct,\n disruption_factor=event.disruption_factor,\n )\n\n # Step 2: Agent swarm\n event_dict = event.model_dump()\n results = await run_aegis_pipeline(event_dict, forecast_data)\n\n return {\n \"success\": True,\n \"timestamp\": datetime.utcnow().isoformat(),\n \"data\": results,\n }\n\n except Exception as e:\n import traceback\n raise HTTPException(status_code=500, detail=f\"{str(e)}\\n{traceback.format_exc()}\")\n\n\n@app.get(\"/api/stream\")\nasync def stream_crisis(\n oil_change: float = 18.0,\n disruption: float = 0.7,\n severity: str = \"HIGH\",\n):\n \"\"\"\n Server-Sent Events stream of agent activations.\n Connect with EventSource in JavaScript for live updates.\n \"\"\"\n async def event_generator() -> AsyncGenerator[str, None]:\n # Yield SSE format: \"data: {json}\\n\\n\"\n def sse(payload: dict) -> str:\n return f\"data: {json.dumps(payload)}\\n\\n\"\n\n yield sse({\"type\": \"start\", \"message\": \"Aegis pipeline initiated\"})\n\n try:\n fc = get_forecaster()\n forecast_data = fc.forecast(\n horizon_days=14,\n crisis_shock=oil_change,\n disruption_factor=disruption,\n )\n yield sse({\"type\": \"forecast_ready\", \"data\": forecast_data[\"summary\"]})\n\n event_dict = {\n \"oil_price_change_pct\": oil_change,\n \"shipping_disruption\": \"Strait of Hormuz disruption detected\",\n \"news_headline\": \"Geopolitical escalation near Persian Gulf\",\n \"severity\": severity,\n \"disruption_factor\": disruption,\n }\n\n # Import individual agents for streaming\n from agents.swarm import (\n signal_agent, intelligence_agent, forecast_agent,\n simulation_agent, decision_agent, alert_agent, execution_agent,\n )\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"signal\", \"index\": 1})\n sig = await signal_agent(event_dict)\n yield sse({\"type\": \"agent_done\", \"agent\": \"signal\", \"data\": sig})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"intelligence\", \"index\": 2})\n intel = await intelligence_agent(sig, event_dict)\n yield sse({\"type\": \"agent_done\", \"agent\": \"intelligence\", \"data\": intel})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"forecast\", \"index\": 3})\n fore = await forecast_agent(intel, forecast_data)\n yield sse({\"type\": \"agent_done\", \"agent\": \"forecast\", \"data\": fore})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"simulation\", \"index\": 4})\n sim = await simulation_agent(fore, event_dict)\n yield sse({\"type\": \"agent_done\", \"agent\": \"simulation\", \"data\": sim})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"decision\", \"index\": 5})\n dec = await decision_agent(sim, fore, intel)\n yield sse({\"type\": \"agent_done\", \"agent\": \"decision\", \"data\": dec})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"alert\", \"index\": 6})\n alert = await alert_agent(dec, fore)\n yield sse({\"type\": \"agent_done\", \"agent\": \"alert\", \"data\": alert})\n\n yield sse({\"type\": \"agent_start\", \"agent\": \"execution\", \"index\": 7})\n exe = await execution_agent(dec)\n yield sse({\"type\": \"agent_done\", \"agent\": \"execution\", \"data\": exe})\n\n yield sse({\n \"type\": \"complete\",\n \"message\": \"All 7 agents completed\",\n \"summary\": dec.get(\"executive_summary\", \"\"),\n \"threat\": dec.get(\"threat_level\", \"\"),\n })\n\n except Exception as e:\n yield sse({\"type\": \"error\", \"message\": str(e)})\n\n return StreamingResponse(\n event_generator(),\n media_type=\"text/event-stream\",\n headers={\n \"Cache-Control\": \"no-cache\",\n \"X-Accel-Buffering\": \"no\",\n },\n )\n\n\n@app.get(\"/api/status\")\nasync def system_status():\n \"\"\"Returns live system status for the dashboard.\"\"\"\n import random\n return {\n \"agents_online\": 7,\n \"uptime_seconds\": int(datetime.utcnow().timestamp()) % 86400,\n \"oil_price\": round(82 + random.uniform(-2, 2), 2),\n \"risk_level\": \"LOW\",\n \"last_event\": None,\n \"groq_model\": \"llama-3.3-70b-versatile\",\n \"forecast_model\": \"ARIMA(2,1,2) + XGBoost\",\n }\n\n\n@app.get(\"/\", response_class=HTMLResponse)\nasync def serve_frontend():\n \"\"\"Serve the demo HTML directly from the API for easy Colab sharing.\"\"\"\n html = \"\"\"\n\n\n\n\nAegis \u2014 Enterprise Crisis Management\n\n\n\n\n\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
AEGIS
Autonomous Enterprise Crisis Management
\n \u25cf ONLINE\n
\n
\n
\n
System State
NOMINAL
\n
Oil ($/bbl)
82
\n
Supply Risk
LOW
\n
Agents Active
0 / 7
\n
\n\n
\n\n
\n \u26a0 Inject Crisis Scenario\n \u21ba Reset\n
\n\n
\n
\n
Oil price forecast (14-day)+3%
\n
\n
\n
\n
Logistics delay risk12%
\n
\n
\n
\n
Estimated cost impact+2%
\n
\n
\n
\n\n
\n\n
\n
Decision Agent \u2014 Recommendations
\n
LOW
No action required
System operating within normal parameters
\n
\n
\n\n\n\n\n\"\"\"\n return html\n\n'''\nwith open(ROOT+\"/api/server.py\",\"w\") as f: f.write(server_code)\n\n# Add marine endpoint to server\nwith open(ROOT+\"/api/server.py\",\"r\") as f: sc = f.read()\nif \"/api/marine\" not in sc:\n marine_endpoint = '''\n@app.get(\"/api/marine\")\nasync def marine_feed():\n try:\n from agents.swarm import scrape_marine_traffic\n data = scrape_marine_traffic()\n return {\"success\": True, \"data\": data}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n'''\n sc = sc.replace(\"@app.get(\\\"/api/status\\\")\", marine_endpoint + '\\n@app.get(\"/api/status\")')\n with open(ROOT+\"/api/server.py\",\"w\") as f: f.write(sc)\n\nprint(\"\u2705 server.py written\")\n\n# Write frontend.html \u2014 full dashboard with marine panel\nimport subprocess\n# Copy from deployment guide embedded frontend\n# The frontend is the complete version with:\n# - Armour shield SVG logo\n# - Shield Against Chaos tagline\n# - Marine Traffic panel\n# - Auto-monitor countdown\n# - All 7 agents with correct IDs\n# - All bugs fixed\nprint(\"\u2705 All files written successfully\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cell 5 \u2014 Launch FastAPI + ngrok\n\u26a1 After this cell runs, **copy the Public URL** and open it in your browser." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import threading, time, subprocess, sys, urllib.request, json\nfrom pyngrok import ngrok, conf\n\n# Fix model name in all files\nfor f in [\"/content/aegis/agents/swarm.py\", \"/content/aegis/api/server.py\"]:\n try:\n content = open(f).read()\n content = content.replace(\"llama-3.1-70b-versatile\",\"llama-3.3-70b-versatile\")\n open(f,\"w\").write(content)\n except: pass\n\n# Kill any existing server\nsubprocess.run([\"pkill\",\"-f\",\"uvicorn\"],capture_output=True)\nsubprocess.run([\"fuser\",\"-k\",\"8000/tcp\"],capture_output=True)\ntime.sleep(2)\n\ndef run_server():\n import os\n env = os.environ.copy()\n env[\"PYTHONPATH\"] = \"/content/aegis\"\n r = subprocess.run([\n sys.executable,\"-m\",\"uvicorn\",\"api.server:app\",\n \"--host\",\"0.0.0.0\",\"--port\",\"8000\",\"--log-level\",\"warning\",\n ], cwd=\"/content/aegis\", capture_output=True, text=True, env=env)\n if r.returncode != 0:\n print(\"\u274c Server error:\", r.stderr[-800:])\n\nthreading.Thread(target=run_server, daemon=True).start()\n\nprint(\"\u23f3 Waiting for server...\")\nfor i in range(20):\n time.sleep(1)\n try:\n urllib.request.urlopen(\"http://localhost:8000/health\",timeout=2)\n print(f\"\u2705 Server up in {i+1}s\")\n break\n except:\n print(f\" [{i+1}/20] waiting...\")\n\n# Connect ngrok\nconf.get_default().auth_token = NGROK_TOKEN\ntry:\n for t in ngrok.get_tunnels(): ngrok.disconnect(t.public_url)\nexcept: pass\ntime.sleep(1)\ntunnel = ngrok.connect(8000,\"http\")\nURL = tunnel.public_url\n\n# Quick health check\ntry:\n import json as _json\n health = _json.loads(urllib.request.urlopen(\n \"http://localhost:8000/health\",timeout=5).read())\n print(f\"\u2705 Health: {health['status']} | {health['agents']} agents | {health['platform']}\")\nexcept Exception as e:\n print(f\"\u26a0\ufe0f Health check: {e}\")\n\nprint()\nprint(\"=\" * 58)\nprint(\"\ud83d\udee1\ufe0f AEGIS IS LIVE\")\nprint(\"=\" * 58)\nprint(f\" Dashboard : {URL}/\")\nprint(f\" API Docs : {URL}/docs\")\nprint(f\" Health : {URL}/health\")\nprint(f\" Marine : {URL}/api/marine\")\nprint(f\" Stream : {URL}/api/stream\")\nprint(\"=\" * 58)\nprint(\" Model : llama-3.3-70b-versatile (Groq)\")\nprint(\" Forecast : ARIMA(2,1,2) + XGBoost hybrid\")\nprint(\" Marine : gCaptain + TradeWinds live scraper\")\nprint(\" Agents : 7 autonomous agents ready\")\nprint(\" Auto-scan : Every 5 minutes autonomously\")\nprint(\"=\" * 58)\nprint(\" Share Dashboard URL with judges!\")\nprint(\" Click Inject Crisis Scenario to demo!\")\nprint(\"=\" * 58)" ] } ] }