OpenAlexScholar Integration Process for Literature Citations in MathModelAgent

The OpenAlexScholar integration process in MathModelAgent involves email validation, API client initialization, paper search with abstract reconstruction, Redis caching, and citation injection into the Writer agent's generated academic papers.

MathModelAgent leverages OpenAlexScholar as a backend service to fetch scholarly metadata and supply literature citations for automated academic writing. The integration pipeline transforms user-provided credentials into a functional citation retrieval system that reconstructs abstracts, caches results, and formats references for LaTeX output. This article examines the complete implementation from the Vue.js frontend through the FastAPI backend to the Writer agent that consumes the citation data.

Prerequisites: Configuring the OpenAlex Email

The integration begins with collecting a valid email address to access OpenAlex's "polite pool." In frontend/src/stores/apiKeys.ts, the application maintains a reactive reference openalexEmail that persists the user's credentials.

When the user submits their email through the API Key dialog, the frontend invokes the validation endpoint. The frontend/src/apis/apiKeyApi.ts module calls POST /validate-openalex-email, which the backend handles in backend/app/routers/modeling_router.py. The router verifies the address by making a test request to https://api.openalex.org/works?mailto={email} and stores the validated email in settings.OPENALEX_EMAIL for global access.

// frontend/src/stores/apiKeys.ts
export const openalexEmail = ref<string>('')

// Validation flow
await validateOpenalexEmail({ email: form.openalex_email })

# backend/app/routers/modeling_router.py

@router.post("/validate-openalex-email", response_model=ValidateOpenalexEmailResponse)
async def validate_openalex_email(request: ValidateOpenalexEmailRequest):
    url = f"https://api.openalex.org/works?mailto={request.email}"
    async with httpx.AsyncClient() as client:
        resp = await client.get(url, timeout=5)
        resp.raise_for_status()
    return ValidateOpenalexEmailResponse(valid=True, message="Email is valid")

Initializing the OpenAlex Client

The core client implementation resides in backend/app/tools/openalex_scholar.py. The OpenAlexScholar class initializes with a task_id for cache isolation and the validated email for API authentication. The constructor sets the base_url to https://api.openalex.org and prepares a custom User-Agent header containing the mailto parameter.


# backend/app/tools/openalex_scholar.py

class OpenAlexScholar:
    def __init__(self, task_id: str, email: str = None):
        self.base_url = "https://api.openalex.org"
        self.email = email
        self.task_id = task_id
        self.headers = {"User-Agent": f"OpenAlexScholar/1.0 (mailto:{email})"} if email else {}

Searching and Reconstructing Paper Metadata

The search_papers(query, limit) method executes the primary literature retrieval logic. It constructs a request to the /works endpoint with a select parameter specifying fields including abstract_inverted_index, authorships, cited_by_count, and publication_year.

OpenAlex returns abstracts as inverted index objects rather than plain text. The client calls _get_abstract_from_index() to reconstruct readable abstracts from this token-position mapping. Each work is then wrapped into a ScholarMessage schema defined in backend/app/schemas/response.py.


# backend/app/tools/openalex_scholar.py

async def search_papers(self, query: str, limit: int = 8) -> List[Dict[str, Any]]:
    params = {
        "search": query,
        "per_page": limit,
        "select": (
            "id,title,display_name,authorships,cited_by_count,doi,"
            "publication_year,biblio,abstract_inverted_index"
        ),
        "mailto": self.email
    }
    
    response = requests.get(
        f"{self.base_url}/works", 
        params=params, 
        headers=self.headers
    )
    response.raise_for_status()
    data = response.json()
    
    # Reconstruct abstracts from inverted index

    for work in data.get("results", []):
        work["abstract"] = self._get_abstract_from_index(
            work.get("abstract_inverted_index")
        )
    return data["results"]

Caching Strategy with Redis

To avoid redundant API calls during iterative paper generation, the integration employs Redis caching via backend/app/services/redis_manager.py. The search_papers method caches results using a key pattern f"openalex:{self.task_id}", ensuring that subsequent invocations for the same modeling task retrieve literature from the cache rather than the OpenAlex API.

This caching layer significantly improves performance when the Writer agent refines citations or regenerates sections of the academic paper.

Injecting Citations into Academic Papers

The backend/app/core/agents/writer_agent.py consumes the OpenAlexScholar service to enrich generated content. When the Writer agent processes a modeling task, it instantiates OpenAlexScholar with the current task.id and global email settings. The agent calls search_papers() with the problem description as the query, then formats the returned metadata into citation strings suitable for academic papers.


# backend/app/core/agents/writer_agent.py

class WriterAgent:
    async def generate_paper(self, task: Task):
        openalex = OpenAlexScholar(task.id, settings.OPENALEX_EMAIL)
        citations = await openalex.search_papers(
            task.problem_description, 
            limit=10
        )
        
        # Format for LaTeX/Markdown

        formatted_refs = [
            f"{c['authorships'][0]['author']['display_name']} "
            f"({c['publication_year']}). {c['title']}."
            for c in citations
        ]
        
        # Inject into LLM prompt

        paper = await self.llm.generate(
            prompt=self._build_prompt(task, formatted_refs)
        )
        return paper

Summary

  • Email Validation: The integration requires a validated OpenAlex email stored in frontend/src/stores/apiKeys.ts and verified via backend/app/routers/modeling_router.py before any API calls execute.
  • Client Architecture: OpenAlexScholar in backend/app/tools/openalex_scholar.py manages the HTTP session, User-Agent headers, and abstract reconstruction from inverted index data.
  • Metadata Extraction: The search_papers() method queries https://api.openalex.org/works with explicit field selection and reconstructs readable abstracts using _get_abstract_from_index().
  • Performance Optimization: Redis caching through backend/app/services/redis_manager.py stores results per task_id to minimize external API requests.
  • Agent Integration: The Writer agent in backend/app/core/agents/writer_agent.py instantiates the scholar client, retrieves relevant papers based on the problem description, and injects formatted citations into the final academic output.

Frequently Asked Questions

Why does OpenAlexScholar require an email address?

OpenAlex provides a "polite pool" of resources for users who identify themselves via the mailto parameter. The integration stores this email in settings.OPENALEX_EMAIL and includes it in every request header to ensure reliable API access and comply with OpenAlex's usage policies.

How does the system handle abstract reconstruction?

The OpenAlex API returns abstracts as abstract_inverted_index objects, which map tokens to their positions in the text. The _get_abstract_from_index() method in backend/app/tools/openalex_scholar.py reverses this mapping to reconstruct the original abstract text before wrapping it in the ScholarMessage schema.

What happens if the same query runs multiple times during paper generation?

The search_papers() method caches results in Redis using the key pattern openalex:{task_id}. Subsequent calls with the same task identifier retrieve data from the cache rather than making redundant requests to the OpenAlex API, improving response times and reducing rate limit consumption.

Which agent is responsible for formatting the citations?

The Writer agent located in backend/app/core/agents/writer_agent.py instantiates OpenAlexScholar, retrieves relevant papers based on the problem description, and formats the authorships, publication_year, and title fields into citation strings suitable for LaTeX or Markdown academic papers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →