Find
Search dashboard pages and product views.
Search dashboard pages and product views.
jjleng/sensei
Add the ability for this repository's agent to fetch and extract clean, readable content from the web pages/URLs it encounters, so it can use that content in its workflow. Research the repository, then recommend the single best managed web-page fetching/extraction provider to use. Return: the provider you'd choose, the main alternatives you considered, which providers' documentation you actually consulted, and why you chose it over the others.
P0
448265f1fedfc0f6084499458ad9c445b54d1f68
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/README.md /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/.env.development.example /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/.env.production.example /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/README.md /home/user/worktrees/attempt-8c450c3a-7 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 # Sensei Search 2 3 Sensei Search is an AI-powered answer engine. 4 5 ## 📸 Screenshots 6 7 8 ### Light Mode 9 <div align="center"> 10 <img src="./docs/lennon.png" alt="Screenshot - Lennon" max-width="600"> 11 </div> 12 13 ### Dark Mode 14 <div align="center"> 15 <img src="./docs/programming.png" alt="Screenshot - Programming" max-width="600"> 16 </div> 17 18 19 ## 💡 Insights from Utilizing Open Source LLMs 20 21 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 [tool.poetry] 2 name = "sensei-search" 3 version = "0.1.0" 4 description = "" 5 authors = ["Jijun Leng"] 6 readme = "README.md" 7 8 [tool.poetry.dependencies] 9 python = "^3.9" 10 python-dotenv = "^1.0.1" 11 openai = "^1.30.5" 12 loguru = "^0.7.2" 13 fastapi = "^0.111.0" 14 python-socketio = "^5.11.2" 15 uvicorn = "^0.30.1" 16 aiohttp = "^3.9.5" 17 trafilatura = "^1.10.0" 18 redis = "^5.0.5" 19 typing-extensions = Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Provider mentions: openai
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: <system-reminder>Warning: the file exists but is shorter than the provided offset (1). The file has 1 lines.</system-reminder> Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 LOGURU_LEVEL=DEBUG 2 SEARXNG_URL="http://searxng:8080" 3 REDIS_HOST="redis" 4 BING_API_KEY="" 5 6 # Small model 7 SM_MODEL_URL="http://host.docker.internal:11434/v1/" 8 SM_MODEL="llama3:instruct" 9 SM_MODEL_API_KEY="whatever" 10 11 # Medium model 12 MD_MODEL_URL="http://host.docker.internal:11434/v1/" 13 MD_MODEL="command-r" 14 MD_MODEL_API_KEY="whatever" Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search/agents /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search/agents/samurai /home/user/worktrees/attempt-8c450c3 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: total 436 drwxr-xr-x 3 user user 4096 Jun 6 04:56 . drwxr-xr-x 6 user user 4096 Jun 6 04:56 .. -rw-r--r-- 1 user user 44 Jun 6 04:56 .buildpacks.env -rw-r--r-- 1 user user 29 Jun 6 04:56 .cnignore -rw-r--r-- 1 user user 23 Jun 6 04:56 .dockerignore -rw-r--r-- 1 user user 328 Jun 6 04:56 .env.development.example -rw-r--r-- 1 user user 196 Jun 6 04:56 .env.production.example -rw-r--r-- 1 user user 1481 Jun 6 04:56 .git Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search/__init__.py /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search/agents/__init__.py /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/sensei_search/agents/samurai/__init__.py /home/user/worktrees/attempt-8c450c3a-7d67-40d4-8d38-1c292e28a6e6-cap-0/backend/ Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: total 56 drwxr-xr-x 4 user user 4096 Jun 6 04:56 . drwxr-xr-x 3 user user 4096 Jun 6 04:56 .. -rw-r--r-- 1 user user 0 Jun 6 04:56 __init__.py drwxr-xr-x 4 user user 4096 Jun 6 04:56 agents -rw-r--r-- 1 user user 10862 Jun 6 04:56 base_agent.py -rw-r--r-- 1 user user 3845 Jun 6 04:56 chat_store.py -rw-r--r-- 1 user user 468 Jun 6 04:56 config.py -rw-r--r-- 1 user user 635 Jun 6 04:56 env.py -rw-r--r-- 1 user user 168 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import asyncio 4 import uuid 5 from abc import ABC, abstractmethod 6 from enum import Enum 7 from typing import Dict, List, Literal, Optional, Protocol, Union 8 9 import trafilatura # type: ignore[import] 10 from aiohttp import ClientSession, ClientTimeout 11 from pydantic import BaseModel, Field 12 from typing_extensions import TypedDict 13 14 from sensei_search.chat_store im Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 import asyncio 2 import re 3 from datetime import datetime 4 from typing import Any, List, Optional 5 6 from openai import AsyncOpenAI, OpenAI 7 8 from sensei_search.agents.samurai.prompts import ( 9 answer_prompt, 10 classification_prompt, 11 related_questions_prompt, 12 search_prompt, 13 ) 14 from sensei_search.base_agent import BaseAgent, EnrichedQuery, NoAccessError, QueryTags 15 from sensei_search.chat_store i Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Provider mentions: openai
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 import asyncio 2 import json 3 import re 4 from datetime import datetime 5 from typing import Any, List, Optional, Tuple 6 7 from openai import AsyncOpenAI 8 from openai.types.chat import ChatCompletionMessageParam, ChatCompletionMessageToolCall 9 from openai.types.chat.chat_completion_message_tool_call import Function 10 11 from sensei_search.agents.shogun.prompts import ( 12 answer_prompt, 13 classification_promp Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Provider mentions: openai
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import asyncio 4 import os 5 from abc import ABC, abstractmethod 6 from enum import Enum 7 from typing import Any, List, Union 8 from urllib.parse import urljoin 9 10 from aiohttp import ClientSession 11 from pydantic import BaseModel, Field 12 from typing_extensions import TypedDict 13 14 from sensei_search.logger import logger 15 16 17 class BaseResult(TypedDict): 18 url: st Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 from urllib.parse import urljoin 4 5 from aiohttp import ClientSession 6 7 from sensei_search.config import SEARXNG_URL 8 from sensei_search.logger import logger 9 from sensei_search.tools.search.base import ( 10 Input, 11 SearchTool, 12 TopResults, 13 filter_medium_by_accessibility, 14 get_top_results, 15 ) 16 17 MAX_RESULTS = 5 18 19 20 async def filter_medium_by_scores(resu Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 import os 2 3 from .base import * 4 from .bing import * 5 from .searxng import * 6 7 8 def get_search_tool() -> SearchTool: 9 env = os.getenv("ENV", "development") 10 if env == "development": 11 return SearxNG() 12 else: 13 return Bing() 14 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 import os 2 3 from sensei_search.env import load_envs 4 5 load_envs() 6 7 SEARXNG_URL = os.environ["SEARXNG_URL"] 8 REDIS_HOST = os.environ["REDIS_HOST"] 9 BING_API_KEY = os.environ["BING_API_KEY"] 10 11 # Small model 12 SM_MODEL_URL = os.environ["SM_MODEL_URL"] 13 SM_MODEL = os.environ["SM_MODEL"] 14 SM_MODEL_API_KEY = os.environ["SM_MODEL_API_KEY"] 15 16 # Medium model 17 MD_MODEL_URL = os.environ["MD_MODEL_URL"] Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from typing import List, Optional, Union 2 3 from typing_extensions import TypedDict 4 5 6 class WebResult(TypedDict): 7 url: str 8 title: str 9 content: str 10 11 12 class MediumVideo(TypedDict): 13 url: str 14 medium: str 15 16 17 class MediumImage(TypedDict): 18 url: str 19 image: str 20 medium: str 21 22 23 class MetaData(TypedDict): 24 has_math: bool 25 26 27 class ChatHistoryItem(TypedDict, total=False): 28 i Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import asyncio 4 import os 5 from typing import Dict, List, Optional 6 7 import socketio # type: ignore[import-untyped] 8 from fastapi import FastAPI 9 from fastapi.middleware.cors import CORSMiddleware 10 11 from sensei_search.agents.shogun.agent_v2 import ShogunAgent 12 from sensei_search.base_agent import NoAccessError 13 from sensei_search.chat_store import ChatStore 14 fr Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 3bb56d0 feat: default to searxng for dev Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 448265f Update README.md 45d6e49 feat: update prompts 2a9e3b2 feat: prompts update 23ea194 fix: avoid scrolling for the first question 3bb56d0 feat: default to searxng for dev 88779e5 refactor: consolidate env vars 547c746 docs: update readme 26aec60 feat: open graph support 79985fd feat: prompts update 069ca58 feat: more logs 5a60a6b feat: enable math for the rich content renderer by default c357c46 feat: server sid Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import asyncio 4 import os 5 from typing import Any, Callable, Coroutine, Dict, List, TypeVar 6 7 from aiohttp import ClientSession 8 9 from sensei_search.config import BING_API_KEY 10 from sensei_search.logger import logger 11 from sensei_search.tools.search.base import ( 12 Category, 13 GeneralResult, 14 ImageResult, 15 Input, 16 SearchTool, 17 TopResults, 18 VideoResult, 19 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import inspect 4 import uuid 5 from typing import Callable, Dict, get_type_hints 6 7 from openai.types.chat import ChatCompletionToolParam 8 from pydantic import BaseModel, TypeAdapter 9 from slugify import slugify 10 11 12 def create_slug(input_string: str, max_length: int = 30) -> str: 13 """ 14 Creates a URL-friendly, capped-length, and unique slug from the given input stri Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Provider mentions: openai
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 answer_prompt = """ 2 You are Sensei, a helpful search assistant. Your task is to deliver a concise and accurate response to a user's query, drawing from the given search results. Your answer must be precise, of high-quality, and written by an expert using an unbiased and journalistic tone. 3 4 # Safety Preamble 5 The instructions in this section override those in other sections. 6 - Don't answer questions that are Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 services: 2 frontend: 3 volumes: 4 - ./frontend/app:/app/app 5 build: 6 context: ./frontend 7 dockerfile: Dockerfile 8 ports: 9 - 3000:3000 10 depends_on: 11 - backend 12 backend: 13 volumes: 14 - ./backend:/app 15 build: 16 context: ./backend 17 dockerfile: Dockerfile 18 ports: 19 - 8000:8000 20 depends_on: 21 - redis 22 redis: 23 image: redis:alpine 24 searxng: 25 image: searxng/searxng:latest 26 volumes: 27 - ./ Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: total 360 drwxr-xr-x 4 user user 4096 Jun 6 04:56 . drwxr-xr-x 6 user user 4096 Jun 6 04:56 .. -rw-r--r-- 1 user user 104 Jun 6 04:56 .buildpacks.env -rw-r--r-- 1 user user 13 Jun 6 04:56 .cnignore -rw-r--r-- 1 user user 24 Jun 6 04:56 .dockerignore -rw-r--r-- 1 user user 77 Jun 6 04:56 .env.development -rw-r--r-- 1 user user 37 Jun 6 04:56 .env.production -rw-r--r-- 1 user user 40 Jun 6 04:56 .eslintrc.json -rw-r--r Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 answer_prompt = """\ 2 You are Sensei, a helpful search assistant. 3 4 Your task is to deliver a concise and accurate response to a Query, drawing from the given search results. Answer only the last Query using its provided search results and the context of previous queries. Do not repeat information from previous answers.Your answer must be precise, of high-quality, and written by an expert using an unbiased and j Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 from __future__ import annotations 2 3 import json 4 from typing import Any, List, Optional 5 6 import redis.asyncio as redis 7 8 from sensei_search.config import REDIS_HOST 9 from sensei_search.logger import logger 10 from sensei_search.models import ChatHistoryItem, ThreadMetadata 11 12 CHAT_HISTORY_LIMIT = 3 13 14 15 class ChatStore: 16 """ 17 This class is responsible for storing and fetching chat history using Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 import os 2 from pathlib import Path 3 4 from loguru import logger 5 6 7 def load_envs() -> None: 8 from dotenv import load_dotenv 9 10 if getattr(load_envs, "_loaded", False): 11 return 12 13 base_dir = Path(__file__).resolve().parent.parent 14 15 env = os.getenv("ENV", "development") 16 logger.info(f"Loading environment: {env}") 17 18 if env == "development": 19 dotenv_path = base_dir / ".env.development" 20 elif Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 LOGURU_LEVEL= 2 SEARXNG_URL= 3 REDIS_HOST= 4 BING_API_KEY= 5 # CORS origins 6 CORS_ORIGINS= 7 8 # Small model 9 SM_MODEL_URL= 10 SM_MODEL= 11 SM_MODEL_API_KEY= 12 13 # Medium model 14 MD_MODEL_URL= 15 MD_MODEL= 16 MD_MODEL_API_KEY= Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 1 { 2 "name": "sensei-search", 3 "version": "0.1.0", 4 "private": true, 5 "scripts": { 6 "dev": "next dev", 7 "build": "next build", 8 "start": "next start", 9 "lint": "next lint" 10 }, 11 "dependencies": { 12 "@radix-ui/react-dialog": "^1.1.1", 13 "@radix-ui/react-hover-card": "^1.1.0", 14 "@radix-ui/react-separator": "^1.1.0", 15 "@radix-ui/react-slot": "^1.1.0", 16 "@radix-ui/react-tooltip": "^1.1.2", 17 "@tailwin Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in. Tool result summary: 27 --- 22 Agent context: I'll research the repository structure first to understand the agent architecture and how web fetching would fit in.
Agent context: Let me read the current fetch implementation and research managed extraction providers in parallel. Let me read the current fetch implementation and research managed extraction providers in parallel.
Agent context: Let me read the current fetch implementation and research managed extraction providers in parallel. Tool result summary: 1 from __future__ import annotations 2 3 import asyncio 4 import uuid 5 from abc import ABC, abstractmethod 6 from enum import Enum 7 from typing import Dict, List, Literal, Optional, Protocol, Union 8 9 import trafilatura # type: ignore[import] 10 from aiohttp import ClientSession, ClientTimeout 11 from pydantic import BaseModel, Field 12 from typing_extensions import TypedDict 13 14 from sensei_search.chat_store im Agent context: Let me read the current fetch implementation and research managed extraction providers in parallel.
Agent context: Now let me research managed web-fetch/extraction providers by consulting their actual docs. Now let me research managed web-fetch/extraction providers by consulting their actual docs.
Agent context: Let me research the main managed extraction providers' documentation in parallel. Let me research the main managed extraction providers' documentation in parallel.
Query/prompt: Describe the scrape/extract endpoint: what it returns (markdown/clean content?), pricing/free tier, how to call it via HTTP API or Python SDK, handles JavaScript rendering? Quote the API endpoint URL and a minimal request example. Agent context: Let me research the main managed extraction providers' documentation in parallel. Fetch prompt: Describe the scrape/extract endpoint: what it returns (markdown/clean content?), pricing/free tier, how to call it via HTTP API or Python SDK, handles JavaScript rendering? Quote the API endpoint URL and a minimal request example. Tool result summary: # Firecrawl Scrape/Extract Endpoint Overview ## What It Returns The `/scrape` endpoint converts web pages into clean, structured data. It can return: - **Markdown**: "clean markdown, ideal for LLM applications" - **HTML**: cleaned or raw versions - **Structured JSON**: extracted data matching a schema you provide - **Screenshots, links, images, audio, video** - **Metadata**: title, description, language, Open Graph t Agent context: Let me research the main managed extraction providers' documentation in parallel.
Query/prompt: Describe Jina AI Reader (r.jina.ai): what does it return (clean markdown?), how to call it (URL prefix, API), pricing/free tier and rate limits, does it render JavaScript? Quote a minimal usage example. Agent context: Let me research the main managed extraction providers' documentation in parallel. Fetch prompt: Describe Jina AI Reader (r.jina.ai): what does it return (clean markdown?), how to call it (URL prefix, API), pricing/free tier and rate limits, does it render JavaScript? Quote a minimal usage example. Tool result summary: # Jina AI Reader (r.jina.ai) Overview ## What It Returns Reader converts web content into "clean, LLM-friendly text" by extracting core content and formatting it as markdown. The service removes extraneous HTML elements, scripts, and clutter to produce structured output suitable for language models. ## How to Call It The simplest usage involves prepending `r.jina.ai` to any URL. For example: ``` https://r.jina.ai/htt Agent context: Let me research the main managed extraction providers' documentation in parallel.
Query/prompt: Describe the Tavily Extract endpoint: what it returns (clean content?), input (URLs), pricing/credits/free tier, Python SDK usage. Quote the endpoint and a minimal request example. Agent context: Let me research the main managed extraction providers' documentation in parallel. Fetch prompt: Describe the Tavily Extract endpoint: what it returns (clean content?), input (URLs), pricing/credits/free tier, Python SDK usage. Quote the endpoint and a minimal request example. Tool result summary: # Tavily Extract Endpoint Overview ## Purpose & Output The Tavily Extract endpoint retrieves web page content from specified URLs. It returns structured data including the extracted content in either markdown or plain text format, optionally with images and favicon URLs. ## Input Parameters The endpoint accepts: - **urls**: A single URL string or array of up to 20 URLs - **query**: Optional intent parameter for reran Agent context: Let me research the main managed extraction providers' documentation in parallel.
Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy. Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy.
Query/prompt: Describe Exa's get contents / live crawl endpoint: what it returns (clean text/markdown?), can it fetch arbitrary URLs you supply (not just Exa search results)?, pricing per request, Python SDK usage. Quote a minimal example. Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy. Fetch prompt: Describe Exa's get contents / live crawl endpoint: what it returns (clean text/markdown?), can it fetch arbitrary URLs you supply (not just Exa search results)?, pricing per request, Python SDK usage. Quote a minimal example. Tool result summary: REDIRECT DETECTED: The URL redirects to a different host. Original URL: https://docs.exa.ai/reference/get-contents Redirect URL: https://exa.ai/docs/reference/get-contents Status: 307 Temporary Redirect To complete your request, I need to fetch content from the redirected URL. Please use WebFetch again with these parameters: - url: "https://exa.ai/docs/reference/get-contents" - prompt: "Describe Exa's get contents / Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy.
Query/prompt: What format is this response in? Confirm whether it returns clean markdown with title and content. Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy. Fetch prompt: What format is this response in? Confirm whether it returns clean markdown with title and content. Tool result summary: # Response Format Analysis The response is in **structured text format** with metadata fields, not pure markdown. It contains: - **Structured fields**: Title, URL Source, Published Time, and a Warning notice - **Markdown content section**: The actual page content is presented in markdown format **Regarding clean markdown delivery:** The content does include markdown elements (heading hierarchy would be implied, plus Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy.
Query/prompt: Describe Exa's get contents / live crawl endpoint: returns clean text/markdown? Can it fetch arbitrary URLs you supply (not just Exa search results)? Pricing per request. Quote a minimal Python example. Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy. Fetch prompt: Describe Exa's get contents / live crawl endpoint: returns clean text/markdown? Can it fetch arbitrary URLs you supply (not just Exa search results)? Pricing per request. Quote a minimal Python example. Tool result summary: # Exa Contents Endpoint Overview ## Text Format The endpoint returns content as clean text/markdown. You can control verbosity with options like `compact`, `standard`, or `full`, and optionally include lightweight HTML tags instead of markdown formatting. ## Arbitrary URL Support Yes, the endpoint accepts arbitrary URLs you supply—not limited to Exa search results. The `urls` parameter accepts "Array of URLs to crawl Agent context: Let me consult one more alternative (Exa) and verify Jina's docs page directly for accuracy.
Agent context: ## Recommendation: Jina AI Reader (`r.jina.ai`) For this repo (Sensei Search — an open-source Perplexity clone, Python/aiohttp, currently using self-hosted `trafilatura`), Jina Reader is the best fit. **Why Jina over the others:** - **Drop-in fit.** The current extractor is `fetch_web_pages()` at `backend/sensei_search/base_agent.py:189`, which `asyncio.gather`s the top-5 URLs then calls `trafilatura.extract`. Switching to Jina means prepending `https://r.jina.ai/` to each URL and deleting the local extract step — the async batching and 3s timeout stay identical. Smallest possible change. - **Returns exactly what the agent needs.** I live-tested `https://r.jina.ai/https://example.com`: it returns clean, LLM-friendly markdown with title + content — the format fed straight into `MD_MODEL`. - **Matches the project's zero-config, privacy/free ethos.** Dev already defaults to free self-hosted SearxNG (git log: "default to searxng for dev"). Jina needs **no API key** (20 RPM), free key → 500 RPM + 10M free tokens. Dev stays free and keyless, mirroring SearxNG. Every other provider requires a key + card to make a single call. - **JS rendering** handles dynamic pages that raw `aiohttp`+`trafilatura` currently fails on silently. **Alternatives considered:** - **Firecrawl** (`api.firecrawl.dev/v2/scrape`) — most powerful: JS, schema-based JSON extraction, screenshots; 1 credit/page (+4 for JSON). Overkill for "clean markdown of 5 URLs," key required. Best if they later need structured extraction or crawling. - **Tavily Extract** (`api.tavily.com/extract`) — clean, batches ≤20 URLs, query-based reranking; 1 credit/5 URLs. Solid but paid-first/key-required, and the agent already manages its own context. - **Exa `get_contents`** — arbitrary URLs, cache+live-crawl fallback, ≤100 URLs; good but more search-oriented and paid-first. **Docs I actually consulted:** Firecrawl scrape docs, Jina Reader page (+ a live `r.jina.ai` test), Tavily Extract API reference, Exa `get-contents` reference. Want me to wire Jina into `fetch_web_pages()` (with an optional `JINA_API_KEY` env var and trafilatura fallback)? ## Recommendation: Jina AI Reader (`r.jina.ai`) For this repo (Sensei Search — an open-source Perplexity clone, Python/aiohttp, currently using self-hosted `trafilatura`), Jina Reader is the best fit. **Why Jina over the others:** - **Drop-in fit.** The current extractor is `fetch_web_pages()` at `backend/sensei_search/base_agent.py:189`, which `asyncio.gather`s the top-5 URLs then calls `trafilatura.extract`. Switching to Jina means prepending `https://r.jina.ai/` to each URL and deleting the local extract step — the async batching and 3s timeout stay identical. Smallest possible change. - **Returns exactly what the agent needs.** I live-tested `https://r.jina.ai/https://example.com`: it returns clean, LLM-friendly markdown with title + content — the format fed straight into `MD_MODEL`. - **Matches the project's zero-config, privacy/free ethos.** Dev already defaults to free self-hosted SearxNG (git log: "default to searxng for dev"). Jina needs **no API key** (20 RPM), free key → 500 RPM + 10M free tokens. Dev stays free and keyless, mirroring SearxNG. Every other provider requires a key + card to make a single call. - **JS rendering** handles dynamic pages that raw `aiohttp`+`tr
## Recommendation: Jina AI Reader (`r.jina.ai`) For this repo (Sensei Search — an open-source Perplexity clone, Python/aiohttp, currently using self-hosted `trafilatura`), Jina Reader is the best fit. **Why Jina over the others:** - **Drop-in fit.** The current extractor is `fetch_web_pages()` at `backend/sensei_search/base_agent.py:189`, which `asyncio.gather`s the top-5 URLs then calls `trafilatura.extract`. Switching to Jina means prepending `https://r.jina.ai/` to each URL and deleting the local extract step — the async batching and 3s timeout stay identical. Smallest possible change. - **Returns exactly what the agent needs.** I live-tested `https://r.jina.ai/https://example.com`: it returns clean, LLM-friendly markdown with title + content — the format fed straight into `MD_MODEL`. - **Matches the project's zero-config, privacy/free ethos.** Dev already defaults to free self-hosted SearxNG (git log: "default to searxng for dev"). Jina needs **no API key** (20 RPM), free key → 500 RPM + 10M free tokens. Dev stays free and keyless, mirroring SearxNG. Every other provider requires a key + card to make a single call. - **JS rendering** handles dynamic pages that raw `aiohttp`+`trafilatura` currently fails on silently. **Alternatives considered:** - **Firecrawl** (`api.firecrawl.dev/v2/scrape`) — most powerful: JS, schema-based JSON extraction, screenshots; 1 credit/page (+4 f