Skip to content

Connect VirusTotal to AI Agents: Automate Hunting and Threat Scans

Learn how to connect VirusTotal to AI agents using Truto's /tools endpoint. Build autonomous threat hunting workflows with LangChain and CrewAI.

Roopendra Talekar Roopendra Talekar · · 10 min read
Connect VirusTotal to AI Agents: Automate Hunting and Threat Scans

You want to connect VirusTotal to an AI agent so your security orchestration system can autonomously investigate Indicators of Compromise (IOCs), extract MITRE ATT&CK mappings, traverse threat infrastructure graphs, and detonate suspicious files. Here is exactly how to do it using Truto's /tools endpoint and SDK, bypassing the need to build and maintain a custom REST integration for the VirusTotal v3 API.

Giving a Large Language Model (LLM) read and write access to your threat intelligence platform requires strict schema enforcement and zero-latency execution. If your team uses ChatGPT, check out our guide on connecting VirusTotal to ChatGPT, or if you are building on Anthropic's models, read our guide on connecting VirusTotal to Claude. For developers building custom autonomous workflows for Security Operations Centers (SOCs) or incident response teams, you need a programmatic way to fetch these tools and bind them to your agent framework.

This guide breaks down exactly how to fetch AI-ready tools for VirusTotal, bind them natively to an LLM using frameworks like LangChain, LangGraph, CrewAI, or the Vercel AI SDK, and execute complex threat hunting workflows. For a deeper look at the architecture behind this approach, refer to our research on architecting AI agents and the SaaS integration bottleneck.

Want to automate your incident response workflows? We can show you how to securely connect AI agents to VirusTotal in minutes. :::

Why a Unified Tool Layer Matters for Agent Security Ops

Before writing a line of integration code, you must decide what layer your agent talks to. Direct API tools - writing one Python function per raw VirusTotal endpoint - look convenient in a sandbox. But in production, they push the vendor's API quirks directly into the LLM's context window.

The LLM has to remember how to format JSON:API relationship payloads, how to paginate through massive lists of DNS resolutions, and when to extract a simple descriptor versus a full object. Every one of those quirks is a hallucination waiting to happen.

A unified tool layer abstracts these quirks behind stable, self-describing JSON schemas. Your agent sees get_single_virus_total_ip_address_by_id, virus_total_files_get_mitre_attack_summary, and virus_total_domains_list_relationships. This provides three concrete safety wins for security engineering teams:

  1. Smaller attack surface for hallucination. The LLM only ever chooses from stable function names with deterministic JSON schemas. It never invents query parameters or guesses at pagination cursors.
  2. Zero data retention pass-through. Security tools operate on sensitive internal files and infrastructure data. By using Truto as a pass-through layer, the raw data is never cached or retained at the integration layer, maintaining your compliance posture.
  3. Framework independence. Your tools remain decoupled from the agent execution layer. You can swap LangChain for Vercel AI SDK tomorrow without rewriting your API integrations.

The Engineering Reality of the VirusTotal API

Giving an LLM access to external threat data sounds simple in a prototype. You write a fetch request and wrap it in a tool decorator. Against complex security infrastructure, this collapses quickly. The VirusTotal v3 API introduces several specific integration challenges that break standard REST assumptions.

The JSON:API Specification Trap

VirusTotal strictly adheres to the JSON:API specification. Standard LLMs are trained to expect flat, intuitive JSON objects. When an agent requests data about an IP address, the VirusTotal API does not just return { "ip": "1.1.1.1", "verdict": "malicious" }.

Instead, it returns a heavily nested structure containing data, type, id, links, and deeply nested attributes and relationships. If you expose this raw schema to an LLM, the model wastes precious tokens reasoning about the JSON:API envelope rather than the threat intelligence inside it. A proxy tool layer maps these endpoints into flat, schema-defined inputs and outputs, allowing the model to focus on security analysis.

Descriptors vs. Full Objects

In VirusTotal, navigating relationship graphs (like finding all subdomains of a malicious domain) introduces a fork in the road: you can either fetch full relationship objects or just their "descriptors" (IDs and limited context).

If you expose raw endpoints to an LLM, it will frequently call the full relationship endpoint for massive datasets, blowing up its context window with megabytes of JSON. Truto isolates these into distinct tools like virus_total_domains_list_relationships and virus_total_domains_list_relationship_descriptors, allowing the agent to explicitly choose whether it needs the full payload or just the metadata.

The Two-Step File Upload Dance

LLMs are terrible at orchestrating multi-step API dances without strict guidance. In VirusTotal, uploading a file larger than 32MB requires first calling a specific endpoint (virus_total_files_get_upload_url) to retrieve a one-time signed URL, and then executing a multipart form POST to that URL.

If you hardcode these interactions into your agent, you will spend your sprints writing defensive integration code. The proxy API approach allows you to expose both endpoints as strict tools, paired with system prompts that teach the agent the exact upload sequence required.

Factual Note on Rate Limits

VirusTotal enforces strict rate limits on quotas (e.g., scanning restrictions or Intelligence search throttling). Truto does not retry, throttle, or apply backoff on rate limit errors. When the VirusTotal API returns an HTTP 429 (Too Many Requests), Truto passes that error directly to the caller. Truto normalizes the upstream rate limit info into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. The agent framework or the caller is strictly responsible for intercepting the 429 status code and implementing exponential backoff or retry logic based on the ratelimit-reset timestamp.

Hero Tools for VirusTotal Intelligence

To build an effective SOC agent, you do not need to expose all 100+ VirusTotal endpoints. You need to equip the agent with high-leverage primitives. Here are the core tools your agent needs to automate incident response workflows.

get_single_virus_total_file_by_id

This tool retrieves the complete analysis report for a given file hash (SHA-256, SHA-1, or MD5), including the threat reputation, AV engine verdicts, and sandbox context.

Contextual usage: This is the workhorse of any SOC triage agent. Whenever an EDR platform alerts on a suspicious file, the agent calls this tool first to determine if the hash is a known threat.

"Analyze the file hash 8b5c92... and summarize the threat reputation, listing any critical sandbox detections."

virus_total_files_get_mitre_attack_summary

Extracts a summarized mapping of MITRE ATT&CK tactics and techniques observed across all integrated sandbox reports for a specific file.

Contextual usage: Critical for threat intel analysts. Instead of manually parsing sandbox execution logs, the agent uses this tool to instantly map a payload to a threat actor's playbook.

"Extract the MITRE ATT&CK techniques associated with this file hash and format them into a table detailing the specific tactics used."

get_single_virus_total_ip_address_by_id

Retrieves the detailed threat reputation and routing context for a specific IPv4 or IPv6 address.

Contextual usage: The starting point for network intrusion investigations. Agents use this to enrich firewall alerts or SIEM logs before deciding to block an IP at the edge.

"Check this IP address 192.168.x.x in VirusTotal and tell me if it has any recent malicious verdicts from security vendors."

virus_total_domains_list_relationships

Lists all objects related to a specific domain by relationship type, such as DNS resolutions, subdomains, or communicating files.

Contextual usage: Used by agents to pivot across threat infrastructure. If a domain is confirmed malicious, the agent calls this tool to uncover the broader network of sibling domains and IP addresses.

"Find all historical IP resolutions and subdomains related to evil-phishing-domain.com to help map out the attacker's infrastructure."

create_a_virus_total_file

Uploads a file directly to VirusTotal for active scanning against 70+ antivirus products and 10+ dynamic analysis sandboxes.

Contextual usage: Used for detonating unknown payloads. Note that the agent must be programmed to handle the analysis ID returned by this tool and poll for results asynchronously.

"Upload this suspicious PDF attachment to VirusTotal for a full scan, and return the analysis ID so we can track the results."

Executes advanced queries against the VirusTotal dataset using the VT Intelligence search syntax.

Contextual usage: Proactive threat hunting. The agent can use this tool to search for files matching specific fuzzy hashes, sizes, metadata characteristics, or generic malware signatures.

"Search VT Intelligence for any files matching the generic ransomware signature uploaded in the last 24 hours, and return the top 5 matches."

For the complete inventory of available VirusTotal tools and their exact JSON schemas, reference the Truto VirusTotal integration page.

Building Multi-Step Workflows

Building an autonomous security agent requires chaining these tools together in a reasoning loop. The agent must fetch initial intelligence, analyze the output, and decide which related artifacts to pivot to next.

Because Truto normalizes the upstream rate limit headers, you can build reliable agent loops that handle API exhaustion gracefully without crashing the integration script.

The Architecture of an Agentic Investigation

When investigating an IOC, the sequence of operations matters. This diagram illustrates how a LangGraph agent interacts with Truto's tool layer to execute a multi-step threat hunt.

sequenceDiagram
    participant UserPrompt as User Prompt
    participant Agent as Agent Framework (LangGraph)
    participant TrutoLayer as Truto Tool Layer
    participant VT as VirusTotal API

    UserPrompt->>Agent: "Investigate this IP address..."
    Agent->>TrutoLayer: Call get_single_virus_total_ip_address_by_id
    TrutoLayer->>VT: Proxy Request (Auth injected)
    VT-->>TrutoLayer: Nested JSON:API Payload
    TrutoLayer-->>Agent: Normalized JSON Output
    
    Agent->>Agent: Analyze IP reputation
    
    Agent->>TrutoLayer: Call virus_total_ip_addresses_list_relationships
    TrutoLayer->>VT: Fetch Relationships (Resolutions)
    VT-->>TrutoLayer: Subdomain & Hash Data
    TrutoLayer-->>Agent: Normalized Relationship Output
    
    Agent-->>UserPrompt: "IP is malicious. Found 3 related phishing domains."

Binding Tools to Your Agent

Here is a concrete example of how to fetch these tools using the Truto TypeScript SDK and bind them to a LangChain agent. This script demonstrates fetching the tools, parsing the schemas, and explicitly handling HTTP 429 rate limit errors returned by the VirusTotal API.

import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { TrutoToolManager } from "truto-langchainjs-toolset";
 
async function runThreatHunt() {
  // 1. Initialize the Truto Tool Manager for your VirusTotal integrated account
  const toolManager = new TrutoToolManager({
    trutoApiKey: process.env.TRUTO_API_KEY,
    integratedAccountId: process.env.VT_INTEGRATED_ACCOUNT_ID,
  });
 
  // 2. Fetch the tools dynamically from the Truto /tools endpoint
  // This returns all the methods we defined on the VirusTotal resources
  const tools = await toolManager.getTools();
  console.log(`Successfully loaded ${tools.length} VirusTotal tools.`);
 
  // 3. Initialize your chosen LLM (Framework agnostic)
  const llm = new ChatOpenAI({
    modelName: "gpt-4o",
    temperature: 0,
  });
 
  // 4. Create the system prompt to guide the SOC agent
  const prompt = ChatPromptTemplate.fromMessages([
    [
      "system",
      "You are an elite SOC analyst. You have access to VirusTotal tools to investigate IOCs. " +
      "If you receive an HTTP 429 Too Many Requests error, you must stop and inform the user " +
      "that the rate limit has been reached, reading the ratelimit-reset header if available."
    ],
    ["human", "{input}"],
    ["placeholder", "{agent_scratchpad}"],
  ]);
 
  // 5. Bind the fetched tools to the agent
  const agent = createToolCallingAgent({ llm, tools, prompt });
  const agentExecutor = new AgentExecutor({ agent, tools });
 
  // 6. Execute the workflow with error handling for Truto's pass-through rate limits
  try {
    const response = await agentExecutor.invoke({
      input: "Investigate the IP address 8.8.8.8. Is it malicious? If it is clean, check if it has any historically malicious file resolutions."
    });
    console.log("Agent Investigation Results:\n", response.output);
  } catch (error) {
    // Truto passes the 429 directly from the upstream provider
    if (error.status === 429) {
      const resetTime = error.headers['ratelimit-reset'];
      console.warn(`VirusTotal rate limit exceeded. Retry after timestamp: ${resetTime}. The caller is responsible for implementing backoff.`);
    } else {
      console.error("Agent execution failed:", error);
    }
  }
}
 
runThreatHunt();

Workflows in Action

When you give an LLM the ability to read and traverse VirusTotal data autonomously, you unlock workflows that previously required a dedicated Tier 1 SOC analyst spending hours jumping between browser tabs. Here are two concrete scenarios.

Workflow 1: Automated Phishing Payload Triage

When a user reports a suspicious email containing a link, the SOC needs to determine if the destination serves malware. An AI agent can trace the entire kill chain autonomously.

"A user reported the domain update-secure-auth.com. Determine if this domain is malicious, find any recent IP resolutions, and check if any of those IPs are hosting malicious files."

Agent Execution Steps:

  1. The agent calls get_single_virus_total_domain_by_id with update-secure-auth.com to check the domain's baseline reputation.
  2. Seeing suspicious flags, it calls virus_total_domains_list_relationships passing resolutions as the relationship parameter to find where the domain points.
  3. The tool returns an IP address. The agent then calls virus_total_ip_addresses_list_relationships passing communicating_files to find payloads associated with that IP.
  4. Finally, it loops through the returned file hashes, calling get_single_virus_total_file_by_id to retrieve the sandbox verdicts for the payloads.

The Output: The agent returns a compiled incident report stating that the domain resolves to an IP address currently hosting a known Emotet dropper, providing the exact file hashes and MITRE ATT&CK techniques observed.

Workflow 2: Threat Actor Infrastructure Hunting

Incident responders often start with a single malicious file hash and need to map out the threat actor's entire infrastructure to generate comprehensive firewall blocklists.

"I have a confirmed malicious hash: 9d1c... Map out the associated infrastructure. Find any domains this file communicates with, and then check the reputation of those domains."

Agent Execution Steps:

  1. The agent calls get_single_virus_total_file_by_id to pull the file's behavioral report.
  2. It calls virus_total_files_list_relationships passing contacted_domains to extract the C2 (Command and Control) servers the file attempts to reach.
  3. For every domain returned in the list, the agent iterates through calls to get_single_virus_total_domain_by_id to pull their threat scores and WHOIS records.
  4. It formats this data into a structured JSON list of domains to be passed to a firewall blocking automation script.

The Output: The agent delivers a clean, actionable list of five C2 domains mapped to the original file hash, along with a summary of their registration dates and current AV detection ratios.

Moving from Scripts to Autonomous SOC

Hardcoding API integrations for security tools results in brittle scripts that break whenever a vendor adds a new nested object to their response schema. By leveraging a unified proxy API layer, you abstract the complexity of JSON:API formatting, OAuth, and pagination away from your LLM.

The model is restricted to a curated list of high-leverage tools with strict JSON inputs. It handles the investigative reasoning, and the infrastructure handles the API mechanics. You stop writing point-to-point connector code and start orchestrating intelligent, autonomous incident response.

FAQ

How does Truto handle VirusTotal rate limits?
Truto does not retry or apply backoff on rate limit errors. When VirusTotal returns an HTTP 429, Truto passes that error directly to your agent, normalizing the headers into IETF standard formats (ratelimit-limit, ratelimit-remaining, ratelimit-reset). Your code must implement the retry logic.
Do I have to use the Model Context Protocol (MCP) to use these tools?
No. While you can use MCP, Truto's /tools endpoint exposes standard JSON schemas that can be bound directly using any major agent framework, including LangChain, LangGraph, CrewAI, or the Vercel AI SDK.
Does Truto store the threat data or file hashes returned by VirusTotal?
No. Truto operates on a zero data retention architecture. It acts strictly as a real-time pass-through proxy layer, ensuring sensitive IOCs and internal files are not cached at the integration layer.
How do agents handle large relationship graphs in VirusTotal?
To prevent blowing up the LLM's context window, Truto provides specific tools for fetching relationship descriptors (IDs only) versus fetching full relationship objects. The agent can be prompted to fetch descriptors first, then query specific IDs as needed.

More from our Blog

PII Redaction for MCP: Stop Leaking SaaS Data to LLMs
Security/Guides/AI & Agents

PII Redaction for MCP: Stop Leaking SaaS Data to LLMs

Architectural patterns for redacting PII and standardizing ATS data from Greenhouse, Lever, and Workday before it reaches LLMs via MCP - with code examples, field-level decision matrices, and compliance checklists.

Yuvraj Muley Yuvraj Muley · · 33 min read