Do you remember the last time you spent hours manually sifting through quarterly reports and NEPSE trading data, painstakingly calculating liquidity ratios and debt-to-equity figures for a portfolio of Nepali companies? I certainly do. The sheer volume of data, coupled with the need for timely, accurate insights, often leaves us playing catch-up, missing critical market shifts. While static dashboards offer a snapshot, they lack the intelligence to dynamically respond to complex queries or autonomously uncover subtle anomalies. We need more than just data visualization; we need an assistant that can think, adapt, and act. This post is for developers and data scientists eager to move beyond generic LLM outputs and build truly intelligent, self-correcting financial analysis systems. We’ll dive deep into architecting an LLM agent that autonomously performs complex financial assessments, adapting to new queries and data structures, and providing actionable insights specifically tailored for the unique Nepali financial landscape.
Key Takeaways
- Persona-Driven Prompting is Foundational: A meticulously crafted system prompt, defining the agent's role, objectives, and constraints, is crucial for guiding its reasoning and ensuring relevant, context-aware outputs.
- Custom Tools Unlock Domain Expertise: Equipping LLM agents with specialized Python functions—for data fetching, calculation, and analysis—transforms them from generalists into powerful domain-specific experts capable of interacting with real-world data sources like NEPSE.
- Error Handling and Observability are Non-Negotiable: Implementing robust try/except blocks in tools and configuring the agent for verbose output and parsing error handling is vital for building production-ready, resilient systems.
- Iterative Refinement is Key: Agent development is an iterative process. Expect to refine prompts, tool definitions, and agent configurations based on observed behaviors and outputs to achieve desired analytical depth.
The Problem: Beyond Manual NEPSE Analysis
The Nepali financial market, while vibrant, presents unique challenges. Data can be fragmented, and timely access to comprehensive, structured information is often difficult. Traditional analytical methods, whether manual spreadsheet work or rule-based scripts, struggle with two core issues: scale and adaptability. Scaling manual analysis across many companies or time periods is resource-intensive and error-prone. Rule-based systems, while efficient for known patterns, fail spectacularly when faced with novel queries or unexpected data structures. Imagine needing to quickly assess a company's financial health, identify unusual trading volumes, and then project potential risks, all based on a natural language query. This is where an intelligent agent shines, offering a flexible, autonomous approach to complex financial assessments that goes beyond the limitations of static reports.
Data and Sources
For this tutorial, we will simulate interaction with a NEPSE API for real-time and historical data. While a comprehensive, free, and publicly accessible NEPSE API suitable for production-level real-time data fetching is challenging to maintain for a blog post, our mock API will demonstrate the architecture effectively. In a real-world scenario, you would integrate with a commercial NEPSE data provider or a robust internal data warehouse. Historical stock price data for publicly listed Nepali companies can often be found on platforms like ShareSansar or from NEPSE's official website, which typically offer downloadable CSVs or provide data via their portal. Our example uses hardcoded data to ensure reproducibility.
Data accessed on 2026-09-18. Mock data represents typical NEPSE structures.
Step 1 — Architecting the Agent's Persona and Core Directives
The first crucial step in building an intelligent agent is defining its identity and mission. Without a clear persona and set of directives, an LLM agent can easily drift into irrelevant responses or fail to leverage its tools effectively. My goal here was to establish a clear role for the agent as a "Nepali Financial Analyst Agent," guiding its reasoning to focus on financial health, anomaly detection, and actionable insights relevant to the Nepali market. This isn't just a generic prompt; it's the agent's constitution.
I crafted a detailed system prompt that outlines its expertise, goals, and limitations. I also configured the `AgentExecutor` to be verbose, allowing me to observe its thought process, and to handle parsing errors gracefully, which is essential for robustness in production.
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
import pandas as pd
import json
import random
# Mock API data for reproducibility
MOCK_NEPSE_DATA = {
"NABIL": {"price": 1250.0, "volume": 150000, "pe_ratio": 18.5, "eps": 67.5, "debt_to_equity": 0.8},
"NTC": {"price": 980.0, "volume": 80000, "pe_ratio": 15.2, "eps": 64.0, "debt_to_equity": 0.4},
"HBL": {"price": 450.0, "volume": 200000, "pe_ratio": 12.1, "eps": 37.0, "debt_to_equity": 1.2},
"UNL": {"price": 2500.0, "volume": 5000, "pe_ratio": 22.0, "eps": 110.0, "debt_to_equity": 0.1},
"CHCL": {"price": 280.0, "volume": 300000, "pe_ratio": 9.8, "eps": 28.5, "debt_to_equity": 1.5},
}
MOCK_HISTORICAL_DATA = {
"NABIL": [
{"date": "2024-01-01", "open": 1200, "high": 1210, "low": 1190, "close": 1205, "volume": 100000},
{"date": "2024-01-02", "open": 1205, "high": 1220, "low": 1200, "close": 1215, "volume": 110000},
{"date": "2024-01-03", "open": 1215, "high": 1250, "low": 1210, "close": 1245, "volume": 150000},
{"date": "2024-01-04", "open": 1245, "high":