How ModelerAgent Analyzes Problems and Constructs Mathematical Models in jihe520/mathmodelagent

The ModelerAgent translates free-form problem descriptions into structured mathematical modeling plans by orchestrating a three-stage LLM workflow that receives user questions, applies a specialized system prompt, and outputs machine-readable JSON specifications.

The jihe520/mathmodelagent repository implements a multi-agent system for automated mathematical modeling. At its core, the ModelerAgent serves as the architectural bridge between natural language problem statements and executable code, converting ambiguous requirements into concrete analytical specifications that drive downstream implementation.

Understanding the ModelerAgent Architecture

The ModelerAgent operates as a specialized async component within the agent-to-agent (A2A) pipeline. Located in backend/app/core/agents/modeler_agent.py, this class inherits from a base agent implementation and exposes a single public entry point: the run() method. This method accepts a CoordinatorToModeler schema object containing user questions and returns a ModelerToCoder schema that downstream agents consume for implementation.

The agent maintains internal state through a chat_history list and relies on the MODELER_PROMPT constant defined in backend/app/core/prompts.py (lines 31-57) to constrain the LLM's behavior. The prompt instructs the model to act as an "experienced modeling hand" and enforce strict JSON output requirements.

The Three-Stage Analysis Workflow

The ModelerAgent processes problem descriptions through a deterministic three-stage pipeline that transforms unstructured input into executable modeling specifications.

Stage 1: Receiving Problem Descriptions via CoordinatorToModeler

The workflow initiates when the coordinating service transmits user questions through the CoordinatorToModeler Pydantic schema. The run() method appends these questions to the conversation history alongside the system prompt:

await self.append_chat_history({"role": "system", "content": self.system_prompt})
await self.append_chat_history({"role": "user", "content": json.dumps(coordinator_to_modeler.questions)})

(source: backend/app/core/agents/modeler_agent.py, lines 23-31)

This initialization establishes the context for the LLM, ensuring the model understands its role as a mathematical modeling specialist before processing the specific problem constraints.

Stage 2: Generating Mathematical Models with the LLM

With the conversation primed, the agent invokes the underlying language model through self.model.chat():

response = await self.model.chat(history=self.chat_history, agent_name=self.__class__.__name__)

The LLM receives the full chat history including the MODELER_PROMPT, which mandates a specific output structure. According to backend/app/core/prompts.py (lines 31-57), the prompt requires the model to generate a flat JSON object containing:

  • eda: Exploratory data analysis suggestions
  • ques1 through quesN: Individual model specifications for each user question
  • sensitivity_analysis: Sensitivity testing recommendations

This strict schema ensures downstream agents can parse the output deterministically without ambiguity.

Stage 3: Parsing and Delivering the ModelingPlan

The raw LLM response undergoes preprocessing to extract valid JSON. The implementation strips markdown code fences and parses the content:

json_str = response.choices[0].message.content
json_str = json_str.replace("```json", "").replace("```", "").strip()
questions_solution = json.loads(json_str)
return ModelerToCoder(questions_solution=questions_solution)

(source: backend/app/core/agents/modeler_agent.py, lines 38-48)

If JSON parsing fails, the agent raises a clear ValueError, preventing corrupted plans from propagating to the Coder Agent. The resulting ModelerToCoder object contains the complete modeling specification ready for implementation.

Deep Dive into the MODELER_PROMPT System Instructions

The efficacy of the mathematical model construction depends on the MODELER_PROMPT defined in backend/app/core/prompts.py. This system prompt constrains the LLM to:

  • Role: Act as an experienced mathematical modeling specialist
  • Task: Build comprehensive models and visualization plans for each submitted question
  • Format: Output strictly valid JSON without nested structures or markdown formatting

The prompt specifically enumerates the required JSON keys (eda, ques1, quesN, sensitivity_analysis), ensuring the LLM addresses every dimension of the mathematical modeling process, from initial data exploration through final sensitivity testing.

Implementation Example

The following async workflow demonstrates how to instantiate and execute the ModelerAgent within the mathmodelagent ecosystem:

import asyncio
from app.core.agents.modeler_agent import ModelerAgent
from app.core.llm.llm import LLM
from app.schemas.A2A import CoordinatorToModeler

async def get_modeling_plan():
    # Initialize the LLM backend

    llm = LLM(model_name="gpt-4o-mini")
    
    # Instantiate the ModelerAgent

    agent = ModelerAgent(task_id="task-1234", model=llm)
    
    # Prepare user questions via the coordinator schema

    coordinator_msg = CoordinatorToModeler(
        questions=[
            "How does temperature affect battery discharge rate?",
            "What is the optimal scheduling algorithm for given resource constraints?"
        ]
    )
    
    # Execute the analysis workflow

    modeling_plan = await agent.run(coordinator_msg)
    
    # Access the structured JSON plan

    print(modeling_plan.questions_solution)

asyncio.run(get_modeling_plan())

This example illustrates the complete pipeline: LLM initialization, agent instantiation, schema-compliant input preparation, and retrieval of the JSON modeling plan suitable for transmission to the Coder Agent.

Summary

  • The ModelerAgent in jihe520/mathmodelagent serves as the critical intermediary between natural language problem descriptions and executable mathematical specifications.
  • Three-stage workflow: Receives CoordinatorToModeler input, processes through LLM with MODELER_PROMPT constraints, and returns ModelerToCoder JSON output.
  • Strict JSON schema: The system prompt enforces flat JSON structures with mandatory keys for EDA, individual question models, and sensitivity analysis.
  • Error handling: Implements robust markdown fence stripping and JSON parsing with explicit ValueError exceptions for malformed outputs.
  • A2A integration: Seamlessly fits into the broader agent architecture, consuming coordinator messages and producing coder-ready specifications.

Frequently Asked Questions

What input format does the ModelerAgent require?

The ModelerAgent expects a CoordinatorToModeler Pydantic schema object containing a list of user questions. The agent serializes these questions to JSON and appends them to the chat history alongside the system prompt before invoking the LLM.

How does the ModelerAgent ensure valid JSON output from the LLM?

The agent applies the MODELER_PROMPT defined in backend/app/core/prompts.py, which explicitly instructs the LLM to output only flat JSON without markdown formatting. Additionally, the parsing logic strips potential markdown code fences (json and ) before attempting JSON deserialization, raising a ValueError if parsing fails.

What specific keys must the LLM include in its JSON response?

According to the source code in prompts.py (lines 31-57), the LLM must generate a JSON object containing: eda for exploratory data analysis recommendations, numbered keys (ques1, ques2, etc.) for each question's model specification, and sensitivity_analysis for testing recommendations.

Which downstream agent consumes the ModelerAgent's output?

The ModelerToCoder schema output feeds directly into the Coder Agent, which interprets the JSON modeling plan and implements the actual Python code for data analysis, model construction, and visualization based on the specifications provided.

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 →