3. Agent Overview#

pycsamt.agents is the workflow layer of pyCSAMT. It packages common MT, AMT, and CSAMT tasks into small executable agents: one agent loads a survey, another checks data quality, another corrects static shift, another prepares inversion files, another runs AI inversion, and another assembles a report. The value is not that every operation becomes automatic; the value is that each operation has the same execution shape, so a workflow can be previewed, run, inspected, checkpointed, and repeated.

The agent layer is broader than LLM usage. Many agents are deterministic and run without an API key. LLM support is added where text understanding or narrative drafting is useful: parsing natural-language requests, choosing a workflow route, generating draft interpretation text, or writing report prose. The scientific data products remain structured outputs inside AgentResult, and those outputs should be reviewed directly.

3.1. Core ideas#

The package is built around four concepts:

Concept

Role

pycsamt.agents.BaseAgent

Abstract base class for every agent. It provides LLM access, cost tracking, JSON extraction, plotting helpers, and common validation helpers.

AgentResult

Standard return object with status, summary, structured data, warnings, optional llm_interpretation, elapsed time, and cost estimate.

Agent coordinator

Ordered workflow executor. It chains agents, maps outputs between steps, supports dry run previews, and checkpoints workflow state.

pycsamt.agents.WorkflowOrchestratorAgent

High-level entry point for natural-language workflow requests. It classifies the request and builds the matching agent chain.

Imports are lazy. Importing pycsamt.agents exposes public names without importing optional provider libraries such as anthropic, openai, google-generativeai, torch, or gradio until a feature needs them. This keeps basic processing and no-LLM workflows lightweight.

3.2. How the pieces fit#

At the lowest level, an agent is just a class with one execute method:

\[R = A(I),\]

where \(I\) is the input dictionary, \(A\) is the agent, and \(R\) is the returned AgentResult. A coordinated workflow repeats that pattern:

config
  -> MTLoaderAgent
  -> DataQCAgent
  -> StaticShiftAgent
  -> PhaseAnalysisAgent
  -> ReportAgent

The step boundary matters. Each step should make clear which object it consumes: raw loaded sites, corrected sites, selected periods, an inversion model, a QC table, or a dictionary of previous results. That explicit data flow is what makes an agent chain easier to audit than a long notebook cell.

3.3. When to use agents#

Use agents when you want a workflow-oriented interface rather than individual low-level function calls.

Task

Recommended entry point

Parse a plain-English request into a structured config

ContextInputAgent

Load EDI, AVG, or J files and inspect station completeness

MTLoaderAgent

Run a reproducible multi-step processing chain

AgentCoordinator

Let pyCSAMT choose the workflow from a request

WorkflowOrchestratorAgent

Prepare inversion inputs

InversionPrepAgent, Occam2DAgent, ModEmAgent, or Mare2DEMAgent

Run AI inversion or model-zoo workflows

AIInversionAgent, Inv2DAgent, Inv3DAgent, EnsembleAgent, JointInversionAgent, ModelZooAgent

Generate final products

ReportAgent, CodeGenerationAgent, EDIExportAgent

Use lower-level pyCSAMT APIs when you need full control of an algorithm’s internal arrays, solver configuration, training loop, or plotting object. Use agents when the built-in input and output contracts match the workflow you want to run.

3.4. Installation#

The base package can be installed without LLM, GPU, or web-interface dependencies:

pip install pycsamt

Install optional provider clients only when you plan to use them:

pip install anthropic
pip install openai
pip install google-generativeai

Install optional AI or web dependencies only for those features:

pip install torch
pip install gradio

Optional dependencies are intentionally lazy. A user can run loading, QC, classical preparation, and many previews without installing a neural backend or an LLM client.

3.5. The AgentResult contract#

Every agent returns AgentResult. The object exposes structured fields and also supports dict-like access to data.

 1>>> from pycsamt.agents import AgentResult
 2>>> result = AgentResult(
 3...     status="needs_review",
 4...     summary="QC finished with warnings.",
 5...     data={"n_stations": 28},
 6...     warnings=["2 stations need review"],
 7... )
 8>>> bool(result)
 9True
10>>> result.status
11'needs_review'
12>>> result.get("n_stations")
1328
14>>> result.warnings[0]
15'2 stations need review'

Only "failed" is false in a boolean test. That means if result: ... allows both "success" and "needs_review" to pass. Use exact status checks when a review state should stop a production workflow.

Important fields:

Field

Meaning

status

"success", "failed", or "needs_review".

summary

Short human-readable description of the run.

data

Agent-specific structured outputs, such as sites, qc_table, workflow_type, paths, figures, metrics, or generated files.

warnings

Non-fatal issues encountered during execution.

llm_interpretation

Optional LLM-generated interpretation text. None in no-LLM mode.

elapsed_seconds

Wall-clock runtime measured by the agent.

cost_estimate_usd

Estimated LLM cost for that agent run.

error and error_fix_hint

Failure details and suggested remediation.

3.6. No-LLM request parsing#

ContextInputAgent converts a plain-English request into a structured workflow configuration. With LLM credentials it can ask the configured model; without credentials it uses deterministic request parsing for common workflow phrases, paths, period ranges, components, output directories, and inversion codes.

 1>>> from pycsamt.agents import AGENT_CONFIG, ContextInputAgent
 2>>> with AGENT_CONFIG.offline():
 3...     result = ContextInputAgent().execute({
 4...         "request": (
 5...             "Run phase tensor analysis on /data/WILLY_EDIs, "
 6...             "period 0.001 to 10 s, save to /out/willy_phase"
 7...         )
 8...     })
 9>>> print(result.status)
10success
11>>> print(result["config"]["workflow"])
12phase_analysis
13>>> print(result["config"]["data_path"])
14/data/WILLY_EDIs
15>>> print(result["config"]["period_range"])
16[0.001, 10.0]
17>>> print(result["config"]["output_dir"])
18/out/willy_phase
19>>> print(result.cost_estimate_usd)
200.0

This result is not yet a processed survey; it is a plan-ready configuration. The warnings list should still be checked, especially when the referenced path does not exist on the current machine or the request lacks an output directory.

3.7. Dry-run workflow preview#

A dry run lets the coordinator describe the chain before executing any step. It is useful before long runs, file-writing steps, AI training, or operations that depend on external executables.

 1>>> from pycsamt.agents import AgentCoordinator, AgentResult, BaseAgent
 2>>>
 3>>> class MiniAgent(BaseAgent):
 4...     def __init__(self, name, payload):
 5...         super().__init__(name)
 6...         self.payload = payload
 7...
 8...     def execute(self, input_data):
 9...         return AgentResult(
10...             status="success",
11...             summary=f"{self.name} complete",
12...             data={**self.payload, "input": input_data},
13...         )
14>>>
15>>> coord = AgentCoordinator(
16...     "overview_demo",
17...     checkpoint_dir="outputs/docs/overview_demo",
18...     verbose=False,
19... )
20>>> coord.add_step(
21...     "load",
22...     MiniAgent("load", {"sites": "SITES:28"}),
23...     description="Load survey",
24... )
25>>> coord.add_step(
26...     "qc",
27...     MiniAgent("qc", {"qc_score": 0.91}),
28...     input_fn=lambda r: {"sites": r["load"]["sites"]},
29...     description="Run QC",
30... )
31>>> preview = coord.execute({"path": "/data/WILLY_EDIs"}, dry_run=True)
32>>> print(preview.status)
33success
34>>> print(preview.summary)
35Workflow preview: 2 steps.
36>>> [(s["name"], s["agent"], s["required"]) for s in preview["steps"]]
37[('load', 'MiniAgent', True), ('qc', 'MiniAgent', True)]

The preview result contains a formatted plan string and a structured steps list. No registered agent’s execute method is called.

3.8. Direct agent execution#

Agents can also be used individually. This is the clearest pattern when you already know which operation you want and want to inspect each intermediate object before moving on.

 1>>> from pycsamt.agents import MTLoaderAgent, DataQCAgent
 2>>> load = MTLoaderAgent().execute({
 3...     "path": "data/AMT/WILLY_DATA/L18PLT",
 4... })
 5>>> if load.status == "success":
 6...     qc = DataQCAgent().execute({
 7...         "sites": load["sites"],
 8...         "output_dir": "outputs/willy_qc",
 9...     })
10...     print(qc.status)
11...     print(qc.summary)

This style is especially useful in notebooks. The Sites object returned by the loader can be inspected, plotted, filtered, or passed to a different agent before any larger workflow is committed.

3.9. Coordinated workflows#

Use pycsamt.agents.AgentCoordinator when several agents should run as a named workflow. Each step can receive either the original configuration or a mapped view of earlier step results.

 1>>> from pycsamt.agents import (
 2...     AgentCoordinator,
 3...     MTLoaderAgent,
 4...     DataQCAgent,
 5...     StaticShiftAgent,
 6...     ReportAgent,
 7... )
 8>>> config = {
 9...     "path": "data/AMT/WILLY_DATA/L18PLT",
10...     "output_dir": "outputs/willy_static_shift",
11... }
12>>> coord = AgentCoordinator(
13...     "static_shift_report",
14...     checkpoint_dir=f"{config['output_dir']}/checkpoints",
15... )
16>>> coord.add_step("load", MTLoaderAgent(), description="Load survey files")
17>>> coord.add_step(
18...     "qc",
19...     DataQCAgent(),
20...     input_fn=lambda r: {
21...         "sites": r["load"]["sites"],
22...         "output_dir": f"{config['output_dir']}/qc",
23...     },
24...     description="Run quality control",
25... )
26>>> coord.add_step(
27...     "static_shift",
28...     StaticShiftAgent(),
29...     input_fn=lambda r: {
30...         "sites": r["load"]["sites"],
31...         "qc_table": r["qc"].get("qc_table"),
32...         "output_dir": f"{config['output_dir']}/static_shift",
33...     },
34...     description="Detect and correct static shift",
35... )
36>>> coord.add_step(
37...     "report",
38...     ReportAgent(),
39...     input_fn=lambda r: {
40...         "workflow_results": r,
41...         "output_dir": f"{config['output_dir']}/report",
42...     },
43...     description="Assemble the workflow report",
44...     required=False,
45... )
46>>> preview = coord.execute(config, dry_run=True)
47>>> print([step["name"] for step in preview["steps"]])
48['load', 'qc', 'static_shift', 'report']

The key idea is the input_fn boundary. The QC step consumes loaded sites. The static-shift step consumes loaded sites plus any QC table the QC agent returned. The report step consumes the dictionary of previous step results. See Agent Coordinator for the full workflow contract.

3.10. Natural-language orchestration#

Use pycsamt.agents.WorkflowOrchestratorAgent when a user request should determine the workflow. The orchestrator can classify requests such as quality control, phase-tensor analysis, Occam2D preparation, ModEM preparation, AI inversion, 2-D inversion, 3-D inversion, ensemble inversion, joint inversion, and full workflows.

 1>>> from pycsamt.agents import AGENT_CONFIG, WorkflowOrchestratorAgent
 2>>> with AGENT_CONFIG.offline():
 3...     result = WorkflowOrchestratorAgent().execute({
 4...         "request": "Run phase tensor and strike analysis",
 5...         "data_path": "data/AMT/WILLY_DATA/L18PLT",
 6...         "output_dir": "outputs/willy_phase",
 7...         "dry_run": True,
 8...     })
 9>>> print(result["workflow_type"])
10phase_analysis
11>>> print([step["name"] for step in result["steps"]])
12['load', 'qc', 'static_shift', 'phase_analysis', 'report']

Remove dry_run when the chain should execute. In executed mode, the orchestrator returns both the built coordinator and the coordinator result so the workflow can still be inspected step by step.

3.11. LLM-assisted interpretation#

Agents inherit provider settings from pycsamt.agents.AGENT_CONFIG unless an explicit per-agent key is supplied.

 1>>> from pycsamt.agents import configure_agents, PhaseAnalysisAgent
 2>>> configure_agents(
 3...     provider="claude",
 4...     api_key="sk-ant-...",
 5...     model="claude-sonnet-4-6",
 6... )
 7>>> result = PhaseAnalysisAgent().execute({
 8...     "path": "data/AMT/WILLY_DATA/L18PLT",
 9...     "output_dir": "outputs/willy_phase",
10... })
11>>> print(result.summary)
12>>> print(result.llm_interpretation)
13>>> print(result.cost_estimate_usd)

llm_interpretation is narrative assistance, not a substitute for the structured result fields, diagnostic figures, or a geophysicist’s review. For provider selection, environment variables, budgets, and custom pricing, see Agent And LLM Configuration.

3.12. AI and model-zoo entry points#

AI inversion agents are available as first-class workflow steps and direct interfaces. They are intended for workflows where a neural inverse model, synthetic training configuration, or model-zoo checkpoint is part of the analysis.

1>>> from pycsamt.agents import ModelZooAgent
2>>> zoo = ModelZooAgent()
3>>> models = zoo.execute({"action": "list"})
4>>> print(models.status)
5success
6>>> print(models.summary)
75 pre-trained models in zoo.
8>>> [item["name"] for item in models["details"][:2]]
9['mt1d-resnet-5layer-v1', 'mt1d-cnn-5layer-v1']

Use Inv2DAgent, Inv3DAgent, EnsembleAgent, and JointInversionAgent for specialized deep-learning workflows. See AI And Model-Zoo Agents for the agent catalogue view and AI inversion agents for the detailed AI inversion workflow guide.

3.13. CLI and web interface#

The agent package also exposes a module CLI:

python -m pycsamt.agents preview "Load /data/WILLY EDIs, QC, PT analysis"
python -m pycsamt.agents list
python -m pycsamt.agents pricing
python -m pycsamt.agents zoo
python -m pycsamt.agents web --port=7860

The web interface requires gradio and can also be started from Python:

1>>> from pycsamt.agents.web import launch
2>>> launch()

The CLI is useful for quick previews, catalogue checks, pricing checks, and model-zoo inspection. The Python API remains the preferred interface for auditable project workflows because it keeps structured results in memory and lets the caller archive them explicitly.

3.14. Outputs and reproducibility#

Agent workflows are designed to be inspectable. A robust workflow should:

  1. Keep the original input path and output directory in the workflow config.

  2. Preserve intermediate AgentResult objects while debugging.

  3. Use dry_run=True before expensive or file-writing runs.

  4. Inspect warnings and error_fix_hint before trusting final products.

  5. Track cost_estimate_usd per agent and session-wide spend through AGENT_CONFIG.

  6. Record checkpoint directories for coordinated workflows.

  7. Use CodeGenerationAgent when a workflow should be converted into a reproducible standalone Python script.

For scientific results, reproducibility also means recording which object a step consumed: raw survey, corrected survey, selected-period survey, AI prediction, conventional inversion output, or full previous-step dictionary. That record is what lets another user distinguish “the report was generated” from “the report was generated from the reviewed corrected data.”

3.15. Where to go next#

Page

Use it for

Agent Catalogue

Choosing the right agent for each task.

Agent Coordinator

Building explicit multi-agent workflows.

Workflow Orchestrator

Natural-language workflow classification and execution.

Agent And LLM Configuration

Provider setup, key resolution, budgets, and pricing.

Foundation And Survey Intake Agents

BaseAgent, AgentResult, ContextInputAgent, MTLoaderAgent, and AgentCoordinator basics.

Processing And Diagnostics Agents

QC, static shift, phase analysis, tensor rotation, tipper analysis, frequency decimation, and denoising.

Forward And Inversion Workflow Agents

Forward modelling and classical inversion preparation.

AI And Model-Zoo Agents

AI inversion, model-zoo, ensemble, joint inversion, and anomaly agents.