fciannella commited on
Commit
e832043
·
1 Parent(s): 4fa815b

loading the langgraph agents issue

Browse files
examples/voice_agent_webrtc_langgraph/pipeline.py CHANGED
@@ -81,72 +81,88 @@ ice_servers = (
81
 
82
  @app.get("/assistants")
83
  async def list_assistants(request: Request):
84
- """Proxy: list assistants from LangGraph server with IDs and basic details.
85
- Returns a list of objects {assistant_id, graph_id, name, description} when available.
 
86
  """
87
  import requests
88
 
89
  base_url = os.getenv("LANGGRAPH_BASE_URL", "http://127.0.0.1:2024").rstrip("/")
90
 
91
- # Build auth header: prefer inbound request Authorization, else env token
92
  inbound_auth = request.headers.get("authorization")
93
  token = os.getenv("LANGGRAPH_AUTH_TOKEN") or os.getenv("AUTH0_ACCESS_TOKEN") or os.getenv("AUTH_BEARER_TOKEN")
94
  headers = {"Authorization": inbound_auth} if inbound_auth else ({"Authorization": f"Bearer {token}"} if token else None)
95
 
96
- # Search for assistant IDs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  try:
98
- search_resp = requests.post(
99
- f"{base_url}/assistants/search",
100
- json={
101
- "metadata": {},
102
- "limit": 100,
103
- "offset": 0,
104
- "sort_by": "assistant_id",
105
- "sort_order": "asc",
106
- "select": ["assistant_id"],
107
- },
108
- timeout=10,
109
- headers=headers,
110
- )
111
- search_resp.raise_for_status()
112
  except Exception as exc: # noqa: BLE001
113
- logger.error(f"Failed to query assistants/search: {exc}")
114
- return JSONResponse(status_code=502, content={"error": "assistants_search_failed"})
115
 
116
- items = []
117
- try:
118
- ids = search_resp.json() or []
119
- if isinstance(ids, dict): # some servers may wrap the list
120
- ids = ids.get("items") or ids.get("results") or []
121
- except Exception: # noqa: BLE001
122
- ids = []
123
-
124
- for entry in ids:
125
- assistant_id = None
126
- if isinstance(entry, dict):
127
- assistant_id = entry.get("assistant_id") or entry.get("id")
128
- elif isinstance(entry, str):
129
- assistant_id = entry
130
- if not assistant_id:
131
- continue
132
- # Fetch details for each assistant id (best-effort)
133
- detail = {"assistant_id": assistant_id}
134
  try:
135
- detail_resp = requests.get(f"{base_url}/assistants/{assistant_id}", timeout=5, headers=headers)
136
- if detail_resp.ok:
137
- d = detail_resp.json() or {}
138
- detail.update(
139
- {
140
- "graph_id": d.get("graph_id"),
141
- "name": d.get("name"),
142
- "description": d.get("description"),
143
- "metadata": d.get("metadata") or {},
144
- }
145
- )
146
- except Exception:
147
- pass
148
- # Compute a friendly display name
149
- md = detail.get("metadata") or {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  display_name = (
151
  detail.get("name")
152
  or md.get("display_name")
@@ -155,9 +171,25 @@ async def list_assistants(request: Request):
155
  or detail.get("assistant_id")
156
  )
157
  detail["display_name"] = display_name
158
- items.append(detail)
159
 
160
- return items
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  async def run_bot(webrtc_connection, ws: WebSocket, assistant_override: str | None = None):
163
  """Run the voice agent bot with WebRTC connection and WebSocket.
 
81
 
82
  @app.get("/assistants")
83
  async def list_assistants(request: Request):
84
+ """Return a list of assistants from LangGraph, with robust fallbacks.
85
+
86
+ Output: List of {assistant_id, graph_id?, name?, description?, display_name}.
87
  """
88
  import requests
89
 
90
  base_url = os.getenv("LANGGRAPH_BASE_URL", "http://127.0.0.1:2024").rstrip("/")
91
 
 
92
  inbound_auth = request.headers.get("authorization")
93
  token = os.getenv("LANGGRAPH_AUTH_TOKEN") or os.getenv("AUTH0_ACCESS_TOKEN") or os.getenv("AUTH_BEARER_TOKEN")
94
  headers = {"Authorization": inbound_auth} if inbound_auth else ({"Authorization": f"Bearer {token}"} if token else None)
95
 
96
+ def normalize_entries(raw_items: list) -> list[dict]:
97
+ results: list[dict] = []
98
+ for entry in raw_items:
99
+ assistant_id = None
100
+ if isinstance(entry, dict):
101
+ assistant_id = entry.get("assistant_id") or entry.get("id") or entry.get("name")
102
+ elif isinstance(entry, str):
103
+ assistant_id = entry
104
+ if not assistant_id:
105
+ continue
106
+ results.append({"assistant_id": assistant_id, **(entry if isinstance(entry, dict) else {})})
107
+ return results
108
+
109
+ # Try GET /assistants first (newer servers)
110
+ items: list[dict] = []
111
  try:
112
+ get_resp = requests.get(f"{base_url}/assistants", params={"limit": 100}, timeout=8, headers=headers)
113
+ if get_resp.ok:
114
+ data = get_resp.json() or []
115
+ if isinstance(data, dict):
116
+ data = data.get("items") or data.get("results") or data.get("assistants") or []
117
+ items = normalize_entries(data)
 
 
 
 
 
 
 
 
118
  except Exception as exc: # noqa: BLE001
119
+ logger.warning(f"GET /assistants failed: {exc}")
 
120
 
121
+ # Fallback: POST /assistants/search (older servers)
122
+ if not items:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  try:
124
+ search_resp = requests.post(
125
+ f"{base_url}/assistants/search",
126
+ json={
127
+ "metadata": {},
128
+ "limit": 100,
129
+ "offset": 0,
130
+ "sort_by": "assistant_id",
131
+ "sort_order": "asc",
132
+ "select": ["assistant_id"],
133
+ },
134
+ timeout=10,
135
+ headers=headers,
136
+ )
137
+ if search_resp.ok:
138
+ data = search_resp.json() or []
139
+ if isinstance(data, dict):
140
+ data = data.get("items") or data.get("results") or []
141
+ items = normalize_entries(data)
142
+ except Exception as exc: # noqa: BLE001
143
+ logger.warning(f"POST /assistants/search failed: {exc}")
144
+
145
+ # Best-effort: enrich with details when possible
146
+ enriched: list[dict] = []
147
+ for item in items:
148
+ detail = dict(item)
149
+ assistant_id = detail.get("assistant_id")
150
+ if assistant_id:
151
+ try:
152
+ detail_resp = requests.get(f"{base_url}/assistants/{assistant_id}", timeout=5, headers=headers)
153
+ if detail_resp.ok:
154
+ d = detail_resp.json() or {}
155
+ detail.update(
156
+ {
157
+ "graph_id": d.get("graph_id"),
158
+ "name": d.get("name"),
159
+ "description": d.get("description"),
160
+ "metadata": d.get("metadata") or {},
161
+ }
162
+ )
163
+ except Exception:
164
+ pass
165
+ md = (detail.get("metadata") or {}) if isinstance(detail.get("metadata"), dict) else {}
166
  display_name = (
167
  detail.get("name")
168
  or md.get("display_name")
 
171
  or detail.get("assistant_id")
172
  )
173
  detail["display_name"] = display_name
174
+ enriched.append(detail)
175
 
176
+ # Final fallback: read local graphs from agents/langgraph.json
177
+ if not enriched:
178
+ try:
179
+ config_path = Path(__file__).parent / "agents" / "langgraph.json"
180
+ with open(config_path, encoding="utf-8") as f:
181
+ cfg = json.load(f) or {}
182
+ graphs = (cfg.get("graphs") or {}) if isinstance(cfg, dict) else {}
183
+ for graph_id in graphs.keys():
184
+ enriched.append({
185
+ "assistant_id": graph_id,
186
+ "graph_id": graph_id,
187
+ "display_name": graph_id,
188
+ })
189
+ except Exception as exc: # noqa: BLE001
190
+ logger.error(f"Failed to read local agents/langgraph.json: {exc}")
191
+
192
+ return enriched
193
 
194
  async def run_bot(webrtc_connection, ws: WebSocket, assistant_override: str | None = None):
195
  """Run the voice agent bot with WebRTC connection and WebSocket.