# Scenarios Source: https://docs.arklex.ai/v0.3.x/build-scenario Define test scenarios in ArkSim by specifying the simulated user's profile, goal, and prior knowledge for realistic agent conversations. ## What is a Scenario? A scenario is a test case that describes who the simulated user is, what they want to accomplish, and what they already know going into the conversation with the agent. ArkSim Workflow ## The Three Core Pillars ### Goal Describes the user's objective, guiding their actions and decisions throughout the conversation. > Plan a purchase of a service robot, focusing on delivery timelines and suitability for commercial use. ### User Profile (Persona) Defines who the simulated user is — their personality, demographics, and behavior — as a natural-language description written in second person. > You are Alex, a 26-year-old operations analyst at a mid-sized logistics company in Chicago. You are analytical, detail-oriented, budget-conscious, and risk-aware. ### Knowledge Provides context that shapes the simulated user's questions and expectations. Also used during **evaluation** to check whether the agent's responses were accurate and consistent with the source. > * `home_insurance_overview.md` \ > The service robot is a 40 kg payload autonomous service robot with 8-hour battery life and \$70,000 price… > * `purchase_options.pdf` \ > The payment plans include full purchase, 12-month leasing, and vendor financing… Think of a scenario as answering three questions: **Who** is this user? **What** do they want? **What** do they know? ## Why ArkSim Scenarios? ArkSim Scenarios let you test and evaluate your agent using realistic, profile-driven simulations of user interactions. Each scenario is built around clearly defined goals and behaviors, enabling structured performance evaluation without requiring a real-world dataset. By using synthetic users, you can run consistent and reproducible tests across a wide range of interaction types, making it easy to scale evaluations and understand how your agent performs before deploying it to real users. *** ## Scenario File Structure A scenario file is a single JSON document containing a list of scenario objects. Each scenario represents one simulated user and one conversation session. ```json theme={null} { "schema_version": "v1", "scenarios": [ { ... }, { ... } ] } ``` For the full scenario schema (all fields and types), see [Schema Reference](./schema-reference#scenarios-scenariosjson). *** ## Full Example ```json theme={null} { "schema_version": "v1", "scenarios": [ { "scenario_id": "123456", "user_id": "123456", "goal": "You want to ask detailed questions about XYZ Insurance car coverage options in your province, including limits, deductibles, and what's actually covered.", "knowledge": [ { "content": "Car Insurance Overview: XYZ Insurance offers mandatory and optional coverages including third-party liability, collision, and comprehensive...", "metadata": { "title": "Car Insurance Overview", "source": "https://www.xyzinsurance.com/products-services/auto-car-insurance", "knowledge_type": "car_insurance_overview", "doc_id": "car_insurance_overview_001" } } ], "user_profile": "You are Priya Chen who is open to experience, conscientious, introverted, agreeable, and emotionally stable. You are a 34-year-old single woman living in Toronto, ON, Canada. As a prospective customer who found XYZ Insurance through an online search, you are analytical and value-oriented with moderate spending habits.", "origin": { "target_agent_capability": "Answer questions about XYZ Insurance products and coverage", "goal_raw": "Ask question about XYZ insurance", "user_attributes": { "sex": "Female", "age": "34", "marital_status": "single", "household_size": "1", "location": "Toronto, ON, Canada", "Household_income": "$50,000 - $74,999", "education": "Bachelor's degree", "Openness": "open to experience", "Conscientiousness": "conscientious", "Extraversion": "introverted", "Agreeableness": "agreeable", "Neuroticism": "emotionally stable", "customer_type": "prospective customer", "discovery_type": "online search", "decision_making_style": "analytical", "purchasing_preference": "value oriented", "spending_behavior": "moderate spending", "loyalty_level": "neutral" } } } ] } ``` *** ## Writing Scenarios You can write scenario files manually. The required fields are `scenario_id`, `user_id`, `goal`, `agent_context`, and `user_profile`: ```json theme={null} { "schema_version": "v1", "scenarios": [ { "scenario_id": "my-scenario-001", "user_id": "user-001", "goal": "You want to find out whether your home insurance policy covers water damage from a burst pipe.", "agent_context": "You are a helpful home insurance assistant for XYZ Insurance.", "user_profile": "You are Jordan, an existing customer from Calgary, AB, Canada. You are detail-oriented and want a clear answer.", } ] } ``` **Tips** * Write `goal` in second person ("You want to...") so it reads naturally as a simulator instruction. * `knowledge` can be omitted if the simulated user has no specific background information. * `origin` can be omitted for hand-authored scenarios. *** ## Multi-Knowledge Scenarios A scenario can include multiple knowledge items by adding additional entries to the `knowledge` list. These items are directly injected into the simulated user's context — there is no retrieval step or external knowledge base involved. ```json theme={null} "knowledge": [ { "content": "Home Insurance Basics: XYZ Insurance provides coverage for your dwelling, contents, and liability...", "metadata": { "title": "Home Insurance Basics" } }, { "content": "Claims Process: To file a claim, you can call the XYZ Insurance claims line or use the online claims portal...", "metadata": { "title": "How to File a Claim" } } ] ``` *** ## How Fields Are Used Downstream Understanding how each field is used helps you decide what to include. | Field | Used By | Description | | ---------------------- | --------------------- | -------------------------------------------------------------------- | | `goal` | Simulator & Evaluator | Directly used in the simulator prompt; the most important field. | | `knowledge[].content` | Simulator & Evaluator | Provides simulated user's background knowledge for the conversation. | | `user_profile` | Simulator | Used as-is in the simulated user prompt to define the persona. | | `knowledge[].metadata` | Not used by ArkSim | For labeling and traceability only. | | `origin` | Not used by ArkSim | Tracks scenario provenance; reference only. | ## Next Steps Once your scenario file is ready, you're ready to run your scenarios and review the results. Execute your scenarios and simulate conversations for review and analysis. # CI Integration Source: https://docs.arklex.ai/v0.3.x/ci-integration Run ArkSim as an automated quality gate in your CI pipeline so every code change is tested against your agent's quality bar before it ships. ## Why run ArkSim in CI? Agents break in non-obvious ways. A prompt tweak, a model upgrade, or a dependency change can silently degrade helpfulness, introduce false information, or cause goal failures — without triggering any unit test. Running ArkSim on every pull request turns quality regression into a CI signal: | Without ArkSim in CI | With ArkSim in CI | | ------------------------------------- | ------------------------------------- | | Regressions found in production | Regressions caught before merge | | Manual spot-checking before releases | Automated evaluation on every PR | | Subjective "looks good to me" reviews | Objective, reproducible metric scores | | No record of quality over time | Artifact history per commit | *** ## Choose your approach | | pytest (custom agent) | HTTP server | | ----------------- | --------------------------------------------- | --------------------------------------------------------- | | **How it works** | ArkSim loads your agent class in-process | ArkSim calls your agent over HTTP | | **Agent type** | Python class subclassing `BaseAgent` | Any HTTP server (any language or framework) | | **CI complexity** | Simple — just run `pytest` | Requires starting, health-checking, and stopping a server | | **Template** | `arksim-pytest.yml` + `test_agent_quality.py` | `arksim.yml` | *** ## Approach 1: pytest with a custom agent Your agent is a Python class that subclasses `BaseAgent`. ArkSim loads it in-process — no HTTP server needed. The pytest test runs simulation and evaluation directly and asserts scores. ### How it works ``` GitHub Actions runner │ ├── 1. Checkout + install dependencies ├── 2. python -m pip install arksim pytest pytest-asyncio ├── 3. python -m pip install -r requirements.txt ├── 4. pytest tests/test_agent_quality.py │ ├── Simulate N conversations (agent runs in-process) │ ├── Evaluate each conversation with an LLM judge │ ├── Generate HTML report │ └── Assert quality thresholds → pass or fail └── 5. Upload artifacts (always runs) ├── arksim-html-report (final_report.html) └── arksim-full-results (simulation + evaluation JSONs) ``` ### Setup Your agent class must implement two methods: ```python theme={null} from arksim.simulation_engine.agent.base import BaseAgent class MyAgent(BaseAgent): async def get_chat_id(self) -> str: # Return a stable ID for the current conversation session return str(id(self)) async def execute(self, user_query: str, **kwargs) -> str: # Your agent logic — return the agent's reply as a string ... ``` If you already have an existing agent, wrap it in a thin adapter: ```python theme={null} class MyAgentAdapter(BaseAgent): def __init__(self, agent_config): super().__init__(agent_config) self.agent = MyExistingAgent() async def get_chat_id(self) -> str: return str(id(self)) async def execute(self, user_query: str, **kwargs) -> str: return await self.agent.process(user_query) ``` Download the GitHub Actions example: ```bash theme={null} arksim examples ci ``` Copy the pytest workflow and test template into your repo: ```bash theme={null} mkdir -p .github/workflows tests cp examples/ci/pytest/arksim-pytest.yml .github/workflows/arksim-pytest.yml cp examples/ci/pytest/test_agent_quality.py tests/test_agent_quality.py ``` Create a `conftest.py` in your `tests/` directory so pytest can resolve your agent and metrics modules: ```python theme={null} # tests/conftest.py import sys import os # Add the project root to sys.path so imports like # `from my_agent import MyAgent` resolve correctly. sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) ``` Create `tests/arksim/scenarios.json` with test cases representative of your agent's real usage: ``` tests/ ├── test_agent_quality.py └── arksim/ ├── scenarios.json ← test inputs (committed) └── results/ ← outputs (add to .gitignore) ``` See [Build Scenarios](./build-scenario) for the schema, and [`examples/bank-insurance`](https://github.com/arklexai/arksim/tree/main/examples/bank-insurance) for a full example. Open `tests/test_agent_quality.py` and update: * Import your agent class (replace `from my_agent import MyAgent`) * Import your custom metrics if needed (replace `from my_metrics import ...`), or remove the custom metrics block entirely to use built-in metrics only * Set `NUMERIC_THRESHOLDS` and `QUALITATIVE_FAILURE_LABELS` to match your quality bar * Adjust `num_convos_per_scenario`, `max_turns`, and `num_workers` as needed In your repo → **Settings → Secrets and variables → Actions**: | Secret | Purpose | | ---------------- | -------------------------------------- | | `OPENAI_API_KEY` | LLM ArkSim uses to evaluate your agent | The workflow triggers automatically on every push to `main` and on every PR. A failing assertion fails the job. *** ## Approach 2: HTTP server Your agent runs as an HTTP server exposing an OpenAI-compatible chat completions endpoint. ArkSim calls it over HTTP during CI — works with any language or framework. ### How it works ``` GitHub Actions runner │ ├── 1. Checkout + install dependencies ├── 2. pip install arksim ├── 3. pip install -r requirements.txt ├── 4. Start your agent as an HTTP server (background) ├── 5. Poll /health until HTTP 200 ├── 6. arksim simulate-evaluate config.yaml │ ├── Simulate N conversations with your agent │ ├── Evaluate each conversation with an LLM judge │ └── Check configured quality thresholds ├── 7. Upload artifacts (always runs) │ ├── arksim-html-report (final_report.html) │ └── arksim-full-results (simulation + evaluation JSONs) └── 8. Exit code → job passes or fails ``` The CLI exits non-zero if any threshold is not met, which fails the job. | Exit code | Meaning | | --------- | ------------------------------------------- | | `0` | All evaluations passed | | `1` | Evaluation failed — a threshold was not met | | `2` | Config / usage error | | `3` | Internal / engine error | ### Setup Download the GitHub Actions example: ```bash theme={null} arksim examples ci ``` Copy the workflow template into your repo: ```bash theme={null} mkdir -p .github/workflows cp examples/ci/github-actions/arksim.yml .github/workflows/arksim.yml ``` Create `arksim/config.yaml` in your repo. Point the `endpoint` at the port where your agent server will listen: ```yaml theme={null} agent_config: agent_type: chat_completions agent_name: my-agent api_config: endpoint: http://localhost:8888/v1/chat/completions headers: Content-Type: application/json body: model: my-model messages: [] scenario_file_path: ./arksim/scenarios.json num_conversations_per_scenario: 3 max_turns: 5 output_file_path: ./arksim/results/simulation.json output_dir: ./arksim/results/evaluation metrics_to_run: - faithfulness - helpfulness - coherence - relevance - goal_completion - agent_behavior_failure generate_html_report: true numeric_thresholds: overall_score: 0.6 goal_completion: 0.8 model: gpt-4o provider: openai num_workers: 10 ``` See [Evaluation](./evaluate-conversation) for all configuration options and the full list of available metrics. If your agent's `requirements.txt` conflicts with ArkSim's dependencies, install them in separate virtual environments so they don't interfere: ```yaml theme={null} - name: Install agent dependencies run: | python -m venv .venv-agent .venv-agent/bin/pip install -r requirements.txt - name: Install ArkSim run: pip install arksim - name: Start agent server run: .venv-agent/bin/python my_agent_server.py --port 8888 & ``` Create `arksim/scenarios.json` with test cases representative of your agent's real usage. See [Build Scenarios](./build-scenario) for the schema, and [`examples/bank-insurance`](https://github.com/arklexai/arksim/tree/main/examples/bank-insurance) for a full example. If you have custom metrics, add them to `arksim/custom_metrics/` and reference them in your `arksim/config.yaml`. See [Custom Metrics](./evaluate-conversation#custom-metrics) for the schema. Open `.github/workflows/arksim.yml` and update the two `TODO` sections: **Start agent server** — replace with your framework's startup command: ```yaml theme={null} - name: Start agent server run: uvicorn my_agent:app --host 0.0.0.0 --port 8888 & env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ``` ```yaml theme={null} - name: Start agent server run: python -m uvicorn my_chain_server:app --port 8888 & env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ``` ```yaml theme={null} - name: Start agent server run: python my_agent_server.py --port 8888 & env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ``` ```yaml theme={null} - name: Start agent server run: adk api_server --port 8888 & env: GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} ``` **Wait for agent** — update the health-check URL if your server uses a different route: ```yaml theme={null} - name: Wait for agent to be healthy run: | for i in $(seq 1 30); do if curl -sf http://localhost:8888/health > /dev/null 2>&1; then exit 0 fi sleep 2 done exit 1 ``` In your repo → **Settings → Secrets and variables → Actions**: | Secret | Purpose | | ---------------- | -------------------------------------------- | | `OPENAI_API_KEY` | LLM ArkSim uses to evaluate your agent | | `AGENT_API_KEY` | *(optional)* API key your agent server needs | The workflow triggers automatically on every push to `main` and on every PR. The job passes or fails based on your configured thresholds. *** ## Quality gates Configure pass/fail thresholds in your config or test file. If any gate is not met the job fails. ### Per-metric thresholds Fail if any conversation's per-metric score falls below the minimum. Built-in turn-level metrics use a 1–5 scale; `goal_completion` and `overall_score` use 0–1: ```yaml theme={null} numeric_thresholds: overall_score: 0.6 goal_completion: 0.8 faithfulness: 3.5 helpfulness: 3.0 ``` ### Qualitative failure labels Fail if any evaluated turn returns one of these labels: ```yaml theme={null} qualitative_failure_labels: agent_behavior_failure: ["false information", "disobey user request"] prohibited_statements: ["violated"] ``` See [Threshold Gates](./evaluate-conversation#threshold-gates) for the full reference on all three gate types. *** ## Viewing the evaluation report After every run — pass or fail — two artifacts are uploaded so you can inspect results regardless of outcome. 1. Open the workflow run in GitHub Actions. 2. Scroll to **Artifacts** at the bottom. 3. Download **arksim-html-report** → unzip → open `final_report.html` in your browser. 4. Download **arksim-full-results** for the raw simulation and evaluation JSONs (useful for programmatic analysis or diffing metric trends across runs). The HTML report shows metric averages, per-conversation scores, and the top failure patterns, giving you enough context to know exactly what to fix. # Contact Source: https://docs.arklex.ai/v0.3.x/contact-email Get in touch with the ArkSim team for support and inquiries. ## Get Help Need assistance with ArkSim? For technical support, bug reports, or questions about using ArkSim, contact us: **Email:** [support@arklex.ai](mailto:support@arklex.ai) *** ## Connect With Us You can also find us on GitHub and LinkedIn. Star the repository, open issues, and contribute. Company news, product updates, and announcements. # E-Commerce Customer Service Agent Source: https://docs.arklex.ai/v0.3.x/e-commerce-customer-service-agent-evaluation End-to-end example of using ArkSim to simulate and evaluate an e-commerce shopping assistant agent with product recommendation and order handling scenarios. ## Overview This example walks through running ArkSim against a shopping assistant agent built for an e-commerce use case. The agent is designed to help customers navigate product discovery, orders, returns, and general shopping queries. The example includes two ready-to-run agent setups you can test against out of the box, and a guide for plugging in your own agent once you're familiar with the setup. *** ## Example Agents You can run the example in two ways: **Option 1** uses the OpenAI API directly (no server, minimal setup). **Option 2** runs a local agent built with the OpenAI Agents SDK (e-commerce knowledge base) via A2A, Chat Completions, or a custom agent connector. A lightweight agent that calls the OpenAI API directly. Quick start with minimal setup. Agent built with the OpenAI Agents SDK, backed by an e-commerce knowledge base; supports A2A, Chat Completions, or custom agent connector. *** ## Scenarios The example ships with a set of pre-built scenarios in `scenarios.json` representing realistic e-commerce customer interactions. Each scenario defines a simulated user with a distinct persona, goal, and background knowledge drawn from product and policy documentation. Sample goals include: * Asking about product availability, specifications, and delivery timelines * Checking order status and tracking a shipment * Initiating or following up on a return or refund request * Comparing products and asking for recommendations Scenarios are defined in `scenarios.json` in the example directory and can be edited or extended to reflect your own use case. *** Before following either path, ensure [ArkSim is installed](./installation) (`pip install arksim`). ## Option 1: OpenAI Agent This agent calls the OpenAI API directly, with no server setup required. ```bash theme={null} export OPENAI_API_KEY="" ``` Run from the `examples/e-commerce` directory: ```bash theme={null} cd examples/e-commerce arksim simulate-evaluate config.yaml ``` *** ## Option 2: OpenAI Agents SDK This agent is a shopping assistant built with the OpenAI Agents SDK, backed by an e-commerce knowledge base. It can be exposed via the A2A Protocol, a Chat Completions-compatible endpoint, or loaded directly as a Python class. In the example directory, use the config file for your chosen interface: * **A2A:** `config_a2a.yaml` (inline agent config; uses `${A2A_API_KEY}`) * **Chat Completions:** `config_chat_completions.yaml` (inline agent config; uses `${AGENT_API_KEY}`) * **Custom agent connector:** `config_custom.yaml` (loads agent directly as a Python class — no server needed) Set the matching environment variable before running. ```bash theme={null} uv venv --python 3.11 source .venv/bin/activate uv pip install -r examples/e-commerce/agent_server/requirements.txt ``` ```bash theme={null} conda create -n ecommerce_venv python=3.11 -y conda activate ecommerce_venv pip install -r examples/e-commerce/agent_server/requirements.txt ``` Exposes an A2A-compatible agent on port `9999`. Run from the repository root: ```bash theme={null} export OPENAI_API_KEY="" export A2A_API_KEY=1234-4567-8910 python -m examples.e-commerce.agent_server.a2a.server ``` Run from the repository root (or the directory that contains the `examples` package). If your layout differs, use the module path that resolves to `agent_server/a2a/server.py` under the e-commerce example. Exposes a Chat Completions–compatible endpoint on port `8888` at `/chat/completions`. Run from the repository root: ```bash theme={null} export OPENAI_API_KEY="" export AGENT_API_KEY=123456 python -m examples.e-commerce.agent_server.chat_completions.server ``` Run from the repository root (or the directory that contains the `examples` package). If your layout differs, use the module path that resolves to `agent_server/chat_completions/server.py` under the e-commerce example. No server needed. The custom agent connector loads `custom_agent.py` directly as a Python class at runtime. Skip this step and proceed to run simulation. In a **new terminal**, from `examples/e-commerce`, run the commands for the same interface you used in step 3. Use the same API key you set there. ```bash theme={null} cd examples/e-commerce export OPENAI_API_KEY="" export A2A_API_KEY=1234-4567-8910 arksim simulate-evaluate config_a2a.yaml ``` ```bash theme={null} cd examples/e-commerce export OPENAI_API_KEY="" export AGENT_API_KEY=123456 arksim simulate-evaluate config_chat_completions.yaml ``` No separate server terminal is needed. From `examples/e-commerce`: ```bash theme={null} cd examples/e-commerce export OPENAI_API_KEY="" arksim simulate-evaluate config_custom.yaml ``` Or run the full pipeline as a Python script: ```bash theme={null} export OPENAI_API_KEY="" python run_pipeline.py ``` *** ## Running with Your Own Agent To test your own backend agent against these scenarios: * **Chat Completions:** Follow the comments in `agent_server/chat_completions/server.py` to swap in your own backend logic or point to your endpoint. * **A2A:** Implement your own A2A executor in `agent_server/a2a/agent_executor.py`. * **Custom:** Subclass `BaseAgent` and point `config_custom.yaml` at your module. See [Custom agent configuration](./simulate-conversation#connection-types) for details. Make sure the `agent_config` field in the config YAML is updated. Then run simulation and evaluation as above. See [Agent configuration](./simulate-conversation#agent-configuration) for supported protocols and how to configure agent connections. *** ## Configuration The example uses a single config file for both simulation and evaluation. ```yaml theme={null} # AGENT CONFIGURATION agent_config: agent_type: chat_completions agent_name: e-commerce api_config: endpoint: https://api.openai.com/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENAI_API_KEY}" body: model: gpt-5.1 messages: - role: system content: >- You are a shopping assistant. Please provide a complete answer to the user's question based on your knowledge. Response within 50 words. # SIMULATION SETTINGS # Path to the scenarios file scenario_file_path: ./scenarios.json # Number of conversations per scenario to generate num_conversations_per_scenario: 1 # Maximum turns per conversation max_turns: 5 # Output file path for simulation results output_file_path: ./results/simulation/simulation.json # Jinja template for the simulated user's system prompt simulated_user_prompt_template: null # EVALUATION SETTINGS # Output directory for evaluation results output_dir: ./results/evaluation # Paths to Python files defining custom # QuantitativeMetric or QualitativeMetric subclasses custom_metrics_file_paths: - ./custom_metrics.py # Built-in metrics to run; if empty, all built-in metrics run metrics_to_run: - faithfulness - helpfulness - coherence - verbosity - relevance - goal_completion - agent_behavior_failure # Generate HTML report generate_html_report: true # Numeric thresholds: per-metric minimum scores on native scale # numeric_thresholds: # overall_score: 0.7 # goal_completion: 0.6 # SHARED SETTINGS # LLM model model: gpt-5.1 # LLM provider provider: openai # Workers for parallel processing num_workers: 50 ``` *** ## Output Results are written under the example directory: | Location | Contents | | ---------------------------------------- | ------------------------------------------------------------------------ | | `./results/simulation/simulation.json` | Simulated conversations from the simulation step | | `./results/evaluation/evaluation.json` | Evaluation results (per-turn and per-conversation scores, unique errors) | | `./results/evaluation/final_report.html` | Interactive HTML report for browsing and sharing results | # Evaluation Source: https://docs.arklex.ai/v0.3.x/evaluate-conversation Use ArkSim to score your agent's responses on helpfulness, coherence, relevance, faithfulness, and goal completion, and surface failure patterns with actionable fixes. ## What is Evaluation? Evaluation analyzes the conversation transcripts produced by simulation and scores your agent across multiple dimensions. The **output** is a set of files summarizing your agent's performance across turns, conversations, and error types. Evaluation *** ## What Gets Evaluated Each agent response is scored on five metrics per turn: | Metric | What it measures | Scale | | ---------------- | ------------------------------------------------------ | ----- | | **Helpfulness** | How effectively the response addresses the user's need | 1–5 | | **Coherence** | Logical flow and clarity of the response | 1–5 | | **Relevance** | How directly the response addresses the user's input | 1–5 | | **Verbosity** | Conciseness; penalizes unnecessarily long responses. | 1–5 | | **Faithfulness** | Whether the response contradicts the user's knowledge | 1–5 | Scores range from **1 (poor)** to **5 (excellent)**, with 3–4 considered good and 4–5 excellent. You can add domain-specific [custom metrics](#custom-metrics) (e.g. product suitability, compliance) via Python files. At the conversation level, two additional scores are computed on a 0–1 scale: * **Goal Completion**: whether the user's goal was fully addressed by the end of the conversation. * **Turn Success Ratio**: proportion of turns with no detected behavior failure. These combine into an **Overall Agent Score** per conversation: `overall_agent_score = turn_success_ratio × 0.75 + goal_completion_score × 0.25` Each conversation is assigned a status based on this score. For the exact status values and thresholds, see [Evaluation output](./schema-reference#evaluation-output-evaluationjson) in the Schema Reference. *** ## Behavior Failure Detection Beyond numeric scores, evaluation detects the type of failure in each underperforming turn: | Failure type | Description | | ---------------------------------- | ------------------------------------------------------------------------- | | `lack of specific information` | Correct but incomplete answer that omits details present in the knowledge | | `failure to ask for clarification` | Proceeds with an assumption instead of asking the user | | `disobey user request` | Completely ignores what the user asked | | `repetition` | Restates previous content without adding value | | `false information` | Directly contradicts what is stated in the knowledge | | `no failure` | No failure detected | Across all conversations, duplicate failures are deduplicated into a **unique errors** list with occurrence counts. When errors are found and a scenario file is available, the evaluator automatically generates **focus files** for targeted reruns (see [Focus Files](#focus-files) below). *** ## Inputs The input to evaluation is the simulation output file (e.g. `simulation.json`) from the [Simulation](./simulate-conversation) step. Knowledge referenced during evaluation comes from your [Scenarios](./build-scenario) file. Evaluation is configured via a YAML file: ```yaml theme={null} # Inputs scenario_file_path: ./examples/path/to/scenario.json simulation_file_path: ./examples/path/to/simulation.json # Model provider: openai model: gpt-5.1 # Execution num_workers: 50 # Metrics metrics_to_run: [ faithfulness, helpfulness, coherence, verbosity, relevance, goal_completion, agent_behavior_failure ] custom_metrics_file_paths: [] # Output output_dir: ./examples/path/to/evaluation generate_html_report: true # Threshold gates (optional — omit or set to null to disable) numeric_thresholds: overall_score: 0.7 faithfulness: 3.5 helpfulness: 3.0 goal_completion: 0.8 qualitative_failure_labels: agent_behavior_failure: ["false information", "disobey user request"] prohibited_statements: ["violated"] ``` For all evaluation config keys, types, and defaults, see [Run configuration → Evaluation keys](./schema-reference#evaluation-keys) in the Schema Reference. *** ## Custom Metrics In addition to the built-in metrics (helpfulness, coherence, relevance, verbosity, faithfulness, goal completion, behavior failure), you can define **custom metrics** in Python and load them via config. List of paths to Python files. Each file is loaded and every public `QuantitativeMetric` or `QualitativeMetric` subclass is instantiated and run. Custom metrics **always run** — they are not filtered by `metrics_to_run`. Names of built-in metrics to run. If empty, all built-in metrics run. Use this to restrict evaluation to a subset of built-ins while still running all custom metrics from `custom_metrics_file_paths`. ### Scope Every custom metric has a **scope** that controls when it runs: | Scope | Runs | Receives | | ------------------ | -------------------------- | -------------------------------------------------------- | | `"turn"` (default) | Once per agent response | The current turn + conversation history up to that point | | `"conversation"` | Once per full conversation | The complete conversation history | Use `"turn"` for response-quality checks (clarity, tone, compliance statements). Use `"conversation"` for end-to-end assessments that only make sense after the whole conversation (goal completion, needs assessment, product suitability). ### Metric Types Produces a **numeric score** (e.g. 0–5). | Step | Detail | | --------- | ---------------------------------------------------- | | Subclass | `QuantitativeMetric` | | Implement | `score(score_input: ScoreInput) -> QuantResult` | | Return | `QuantResult` with `name`, `value` (float), `reason` | ```python theme={null} from arksim.evaluator import ( QuantitativeMetric, QuantResult, ScoreInput, ) # Turn-level: scored on every agent response class ClarityScore(QuantitativeMetric): def __init__(self, llm=None): super().__init__(name="clarity", score_range=(0, 5), llm=llm, scope="turn") def score(self, score_input: ScoreInput) -> QuantResult: # self.llm is the evaluator's configured LLM, injected automatically. # score_input.chat_history, .current_turn, .user_goal, .knowledge, etc. value = ... # your scoring logic using self.llm or any other logic return QuantResult(name="clarity", value=value, reason="...") # Conversation-level: scored once after the full conversation class ProductSuitabilityScore(QuantitativeMetric): def __init__(self, llm=None): super().__init__(name="product_suitability", score_range=(0, 5), llm=llm, scope="conversation") def score(self, score_input: ScoreInput) -> QuantResult: # score_input.chat_history contains the full conversation. value = ... return QuantResult(name="product_suitability", value=value, reason="...") ``` Produces a **categorical label** (e.g. `"complete"` / `"partial"`). | Step | Detail | | --------- | ------------------------------------------------- | | Subclass | `QualitativeMetric` | | Implement | `evaluate(score_input: ScoreInput) -> QualResult` | | Return | `QualResult` with `name`, `value` (str), `reason` | ```python theme={null} from arksim.evaluator import ( QualitativeMetric, QualResult, ScoreInput, ) # Turn-level: checked on every agent response class ProhibitedStatements(QualitativeMetric): def __init__(self, llm=None): super().__init__(name="prohibited_statements", llm=llm, scope="turn") def evaluate(self, score_input: ScoreInput) -> QualResult: # self.llm is the evaluator's configured LLM, injected automatically. # score_input.chat_history, .current_turn, .user_goal, .knowledge, etc. label = ... # "ok" | "violated" return QualResult(name="prohibited_statements", value=label, reason="...") # Conversation-level: checked once after the full conversation class NeedsAssessment(QualitativeMetric): def __init__(self, llm=None): super().__init__(name="needs_assessment", llm=llm, scope="conversation") def evaluate(self, score_input: ScoreInput) -> QualResult: # score_input.chat_history contains the full conversation. label = ... # "complete" | "partial" | "missing" return QualResult(name="needs_assessment", value=label, reason="...") ``` ### Available fields Both metric types receive a `ScoreInput`: ```python theme={null} score_input.chat_history # Full conversation turns score_input.user_goal # The goal the user was trying to achieve score_input.knowledge # Retrieved knowledge / context passed to the agent ``` *** ## Threshold Gates Threshold gates let you fail the CLI with a non-zero exit code when evaluation results fall below acceptable levels. All three gate types are evaluated after every `arksim evaluate` or `arksim simulate-evaluate` run. ### `numeric_thresholds` Per-metric minimum scores on each metric's native scale. The mean score across all turns per conversation is compared against the threshold. Any conversation that falls below the threshold fails the run with exit code 1. | Metric | Scale | Notes | | -------------------------------------------------------------------- | ---------- | -------------------------------------------------------- | | `overall_score` | 0–1 | Per-conversation `overall_agent_score` compared directly | | `faithfulness`, `helpfulness`, `coherence`, `verbosity`, `relevance` | 1–5 | Mean of per-turn scores | | `goal_completion` | 0–1 | Per-conversation score compared directly | | Custom quantitative metrics (`scope="turn"`) | Your scale | Mean of per-turn scores | | Custom quantitative metrics (`scope="conversation"`) | Your scale | Per-conversation score compared directly | ```yaml theme={null} numeric_thresholds: overall_score: 0.7 faithfulness: 3.5 helpfulness: 3.0 goal_completion: 0.8 ``` ### `qualitative_failure_labels` Hard-gate failure labels for qualitative metrics. Any evaluated turn whose label appears in the list fails the run with exit code 1. Turns where the metric did not run are skipped. ```yaml theme={null} qualitative_failure_labels: agent_behavior_failure: ["false information", "disobey user request"] prohibited_statements: ["violated"] ``` If any gate fails, the CLI exits with code `1` and logs which conversations and turns did not meet the requirement. See [Exit codes](./schema-reference#exit-codes) for the full list of exit codes. ### Programmatic threshold gates When running ArkSim programmatically (e.g. with a custom agent class), you can apply the same gates by importing `check_numeric_thresholds` and `check_qualitative_failure_labels` directly from `arksim.evaluator`: ```python theme={null} import sys from arksim.evaluator import ( Evaluator, check_numeric_thresholds, check_qualitative_failure_labels, ) evaluator_output = evaluator.evaluate(simulation_output) numeric_ok = check_numeric_thresholds( evaluator_output, numeric_thresholds={ "clarity": 3.5, "goal_completion": 0.6, }, ) qual_ok = check_qualitative_failure_labels( evaluator_output, qualitative_failure_labels={ "agent_behavior_failure": ["false information"], "prohibited_statements": ["violated"], }, ) if not numeric_ok or not qual_ok: sys.exit(1) ``` You can also write your own custom gate by inspecting `evaluator_output.conversations` directly and applying any logic you need: ```python theme={null} # Example: fail if any conversation has overall_agent_score below 0.7 for convo in evaluator_output.conversations: if convo.overall_agent_score < 0.7: print(f"Conversation {convo.conversation_id} failed: score {convo.overall_agent_score:.2f}") sys.exit(1) ``` *** ## Running Evaluation ```bash theme={null} pip install arksim ``` ```bash theme={null} arksim evaluate config.yaml ``` ```python theme={null} from arksim.evaluator import run_evaluation, EvaluationInput evaluation_results = run_evaluation(EvaluationInput( simulation_file_path="./simulation.json", scenario_file_path="./scenarios.json", output_dir="./evaluation", model="gpt-5.1", provider="openai", num_workers=50, generate_html_report=True, )) ``` ```python theme={null} from arksim.scenario import Scenarios from arksim.evaluator import run_evaluation, EvaluationInput # simulation comes from run_simulation(...) scenarios = Scenarios.load("./scenarios.json") evaluation_results = run_evaluation(EvaluationInput( output_dir="./evaluation", model="gpt-5.1", provider="openai", num_workers="auto", generate_html_report=True, ), simulation=simulation, scenarios=scenarios) ``` *** ## Output Files | File | Description | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `evaluation.json` | Full evaluation output: conversations with scores, failure labels, and unique errors. See [Evaluation output](./schema-reference#evaluation-output-evaluationjson) for the schema. | | `final_report.html` | High-level summary with metric averages, overall assessment, and top unique errors, rendered for easier browsing and sharing. | | `focus/error_N.json` | Filtered scenario file for error group N (sorted by severity). Only appears when unique errors are detected and a scenario file is provided. See [Focus Files](#focus-files). | | `focus/all_failures.json` | Union of all failing scenarios across every error group. Use this to rerun everything that failed in one pass. | *** ## Reading the Output Results go to `evaluation.json`: **conversations** (one per run), **unique\_errors** (deduplicated failures), and **error\_scenario\_mappings** (which scenarios triggered each error). Each `conversations[]` entry has: * **`overall_agent_score`** (0–1): Turn success + goal completion. Use to rank or filter. * **`evaluation_status`**: `Done`, `Partial Failure`, `Failed`, or `Evaluation Failed`. * **`goal_completion_score`** (0–1, or -1 if skipped): How fully the goal was addressed. **`goal_completion_reason`** explains it. * **`turn_success_ratio`** (0–1): Share of turns with no behavior failure. Use **`turn_scores[]`** for a turn: `turn_id`, **`scores`** (e.g. helpfulness, faithfulness), **`turn_behavior_failure`**, **`turn_behavior_failure_reason`**, **`unique_error_ids`**. Match IDs to **`unique_errors`** for category and description. Each **`unique_errors[]`** entry has: * **`unique_error_description`**: What went wrong. * **`behavior_failure_category`**: e.g. `false information`, `failure to ask for clarification`, `repetition`. * **`severity`**: e.g. `critical`, `high`, `medium`, `low`. * **`occurrences`**: `{ "conversation_id", "turn_id" }` list. Use to find the conversation and turn in logs or CSV. Use **`occurrences`** to go from an error to the exact turn; then check **`turn_scores`** and the transcript. Each **`error_scenario_mappings[]`** entry maps one unique error to the scenarios that triggered it: * **`unique_error_id`**: Links to the matching entry in `unique_errors`. * **`scenario_ids`**: Which scenarios triggered this error. Use these IDs with `--scenario_file_path` to rerun only the affected scenarios. * **`severity`** and **`error_description`**: Same as the linked `unique_errors` entry, included for convenience. This field is empty when no errors are detected or no scenario file was provided. See [Focus Files](#focus-files) for the file-based workflow. *** ## Focus Files When evaluation detects unique errors and a scenario file is provided, the evaluator generates **focus files** in a `focus/` subdirectory. These are filtered scenario files that let you rerun only the failing subset without any manual config. ### How it works Each unique error group is mapped back to the scenarios that triggered it. The evaluator writes one JSON file per error group plus a combined file with all failing scenarios: ``` evaluation/ evaluation.json final_report.html focus/ error_1.json # scenarios for the highest-severity error error_2.json # scenarios for the second error all_failures.json # union of all failing scenarios ``` Error files are numbered by severity (critical first, then high, medium, low) and by occurrence count within the same severity level. Each focus file uses the standard [Scenarios schema](./schema-reference#scenario-input-scenariosjson), so it works directly with `--scenario_file_path`: ```bash theme={null} # Rerun only the scenarios that triggered error group 1 arksim simulate-evaluate config.yaml \ --scenario_file_path ./evaluation/focus/error_1.json # Or rerun all failing scenarios at once arksim simulate-evaluate config.yaml \ --scenario_file_path ./evaluation/focus/all_failures.json ``` Pass a separate `--output_dir` for each rerun so results do not overwrite the original evaluation. Each rerun produces its own evaluation, report, and focus files (or no focus files if everything passes). ### Iterative fix workflow Focus files support an iterative fix-and-verify loop: 1. Run `arksim simulate-evaluate config.yaml` and review the errors 2. Fix the highest-severity bug in your agent 3. Rerun with the focus file: `--scenario_file_path ./evaluation/focus/error_1.json --output_dir ./results/rerun_1` 4. If the error is resolved, move to the next error group 5. When all targeted reruns pass, do a full battle test with the original scenario file The focus set shrinks as you fix bugs. Scenarios that pass on rerun will not appear in the new run's focus files. # Installation Source: https://docs.arklex.ai/v0.3.x/installation Install ArkSim and get ready to simulate and evaluate your AI agents. ## Requirements * Python 3.10 or later (up to 3.13) * An API key from a supported LLM provider ([OpenAI](https://developers.openai.com/api/docs), [Anthropic](https://platform.claude.com/docs/en/home), or [Google](https://ai.google.dev/gemini-api/docs/api-key)) ## Install from PyPI ```bash theme={null} pip install arksim ``` ### Optional provider extras ArkSim uses OpenAI by default. To use other providers, install the corresponding extra: ```bash theme={null} # Anthropic pip install "arksim[anthropic]" # Google pip install "arksim[google]" # All providers pip install "arksim[all]" ``` ## Install from source ```bash theme={null} git clone https://github.com/arklexai/arksim.git cd arksim pip install -e ".[dev]" ``` This installs in editable mode with test dependencies (`pytest`, `pytest-asyncio`). ## Verify installation ```bash theme={null} arksim --help ``` You should see the available commands: `simulate`, `evaluate`, `simulate-evaluate`, `show-prompts`, `examples`, and `ui`. You're all set! Continue to the [Quickstart guide](./quickstart) to run your first simulation. # Insurance Customer Service Agent Source: https://docs.arklex.ai/v0.3.x/insurance-customer-service-agent-evaluation End-to-end example of using ArkSim to simulate and evaluate an insurance customer service agent with custom compliance metrics and adversarial scenarios. ## Overview This example walks through running ArkSim against a customer service agent built for an insurance company (XYZ Insurance, part of XYZ Bank Group). The agent is designed to answer customer questions about insurance products and coverage, including topics like policy details, claims processes, deductibles, and coverage limits. The example includes two ready-to-run agent implementations you can test against out of the box, and a guide for plugging in your own agent once you're familiar with the setup. *** ## Example Agents A lightweight agent that calls the OpenAI API directly. Quick start with minimal setup. Agent built with the OpenAI Agents SDK, backed by an insurance knowledge base; supports A2A, Chat Completions, or custom agent connector. *** ## Scenarios The example ships with a set of pre-built scenarios in `scenarios.json` representing realistic insurance customer interactions. Each scenario defines a simulated user with a distinct persona, goal, and background knowledge drawn from insurance product documentation. The scenario goals are: * Learn how home insurance deductibles work, when to file a claim, and how they affect your premium and payout. * Get a denied water damage claim (water heater 17 years old; policy excludes tanks 15+) overturned or learn how to fight it, including legal options; push back if the agent only repeats the policy. * Renew Basic Form home insurance at the same price; push back if the agent upsells Broad or Comprehensive Form or extra features. * Get a clear recommendation and dollar amount for personal condo insurance as a first-time buyer, without lengthy needs questions. * Bundle home, two cars, and motorcycle with XYZ and get a specific savings number; resist needs questions or comparisons. Scenarios are defined in `scenarios.json` in the example directory and can be edited or extended to reflect your own use case. *** Before following either path, ensure [ArkSim is installed](./installation) (`pip install arksim`). ## Option 1: OpenAI Agent This agent calls the OpenAI API directly, with no server setup required. ```bash theme={null} export OPENAI_API_KEY="" ``` Run from the `examples/bank-insurance` directory: ```bash theme={null} cd examples/bank-insurance arksim simulate-evaluate config.yaml ``` *** ## Option 2: In-house Agent (OpenAI Agents SDK) This agent is a customer service agent built with the OpenAI Agents SDK, backed by an insurance knowledge base. It can be exposed via either the A2A Protocol or a Chat Completions-compatible endpoint. In the example directory, use the config file for your chosen interface: * **A2A:** `config_a2a.yaml` (inline agent config; uses `${A2A_API_KEY}`) * **Chat Completions:** `config_chat_completions.yaml` (inline agent config; uses `${AGENT_API_KEY}`) * **Custom agent connector:** `config_custom.yaml` (loads agent directly as a Python class — no server needed) Set the matching environment variable before running. ```bash theme={null} uv venv --python 3.11 source .venv/bin/activate pip install -r examples/bank-insurance/agent_server/requirements.txt ``` ```bash theme={null} conda create -n bank_venv python=3.11 -y conda activate bank_venv pip install -r examples/bank-insurance/agent_server/requirements.txt ``` Or from inside the example directory: `pip install -r agent_server/requirements.txt` Exposes an A2A-compatible agent on port `9999`. Run from the repository root: ```bash theme={null} export OPENAI_API_KEY="" export A2A_API_KEY=1234-4567-8910 python -m examples.bank-insurance.agent_server.a2a.server ``` Run from the repository root (or the directory that contains the `examples` package). If your layout differs, use the module path that resolves to `agent_server/a2a/server.py` under the bank-insurance example. Exposes a Chat Completions–compatible endpoint on port `8888` at `/chat/completions`. Run from the repository root: ```bash theme={null} export OPENAI_API_KEY="" export AGENT_API_KEY=123456 python -m examples.bank-insurance.agent_server.chat_completions.server ``` Run from the repository root (or the directory that contains the `examples` package). If your layout differs, use the module path that resolves to `agent_server/chat_completions/server.py` under the bank-insurance example. No server needed. The custom agent connector loads `custom_agent.py` directly as a Python class at runtime. Skip this step and proceed to run simulation. In a **new terminal**, from `examples/bank-insurance`, run the commands for the same interface you used in step 3. Use the same API key you set there. ```bash theme={null} cd examples/bank-insurance export A2A_API_KEY=1234-4567-8910 arksim simulate-evaluate config_a2a.yaml ``` ```bash theme={null} cd examples/bank-insurance export AGENT_API_KEY=123456 arksim simulate-evaluate config_chat_completions.yaml ``` No separate server terminal is needed. From `examples/bank-insurance`: ```bash theme={null} cd examples/bank-insurance export OPENAI_API_KEY="" arksim simulate-evaluate config_custom.yaml ``` Or run the full pipeline as a Python script: ```bash theme={null} export OPENAI_API_KEY="" python run_pipeline.py ``` *** ## Running with Your Own Agent To test your own backend agent against these scenarios: * **Chat Completions:** Follow the comments in `agent_server/chat_completions/server.py` to swap in your own backend logic or point to your endpoint. * **A2A:** Implement your own A2A executor in `agent_server/a2a/agent_executor.py`. * **Custom:** Subclass `BaseAgent` and point `config_custom.yaml` at your module. See [Custom agent configuration](./simulate-conversation#connection-types) for details. Make sure the `agent_config` field in the config YAML is updated. Then run simulation and evaluation as above. See [Agent configuration](./simulate-conversation#agent-configuration) for supported protocols and how to configure agent connections. *** ## Configuration The example uses a single config file for both simulation and evaluation. ```yaml theme={null} # AGENT CONFIGURATION agent_config: agent_type: chat_completions agent_name: bank-insurance api_config: endpoint: https://api.openai.com/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENAI_API_KEY}" body: model: gpt-5.1 messages: - role: system content: >- You are a customer service chatbot for XYZ Bank insurance. XYZ Insurance—a core business within XYZ Bank Group—is one of Canada's leading providers of life, health, home, auto, and travel insurance. Rules: 1. Do not flip roles. 2. Avoid using bullet points or lists. 3. Never exceed 80 words. # SIMULATION SETTINGS # Path to the scenarios file scenario_file_path: ./scenarios.json # Number of conversations per scenario to generate num_conversations_per_scenario: 1 # Maximum turns per conversation max_turns: 5 # Output file path for simulation results output_file_path: ./results/simulation/simulation.json # Jinja template for the simulated user's system prompt simulated_user_prompt_template: null # EVALUATION SETTINGS # Output directory for evaluation results output_dir: ./results/evaluation # Paths to Python files defining custom # QuantitativeMetric or QualitativeMetric subclasses custom_metrics_file_paths: - ./custom_metrics.py # Built-in metrics to run; if empty, all built-in metrics run metrics_to_run: - faithfulness - helpfulness - coherence - relevance - goal_completion - agent_behavior_failure # Generate HTML report generate_html_report: true # Numeric thresholds: per-metric minimum scores on native scale # numeric_thresholds: # overall_score: 0.7 # goal_completion: 0.6 # SHARED SETTINGS # LLM model model: gpt-5.1 # LLM provider provider: openai # Workers for parallel processing num_workers: 50 ``` *** ## Output Results are written under the example directory: | Location | Contents | | ---------------------------------------- | ------------------------------------------------------------------------ | | `./results/simulation/simulation.json` | Simulated conversations from the simulation step | | `./results/evaluation/evaluation.json` | Evaluation results (per-turn and per-conversation scores, unique errors) | | `./results/evaluation/final_report.html` | Interactive HTML report for browsing and sharing results | # Overview Source: https://docs.arklex.ai/v0.3.x/overview ArkSim is an open-source agent testing framework that simulates realistic multi-turn conversations with your AI agent and evaluates performance across built-in and custom metrics. ## What is ArkSim? ArkSim is an open-source agent testing tool designed to help developers validate, simulate, and harden their agent systems. It focuses on reproducible interaction simulations to identify reliability and idempotency gaps before production deployment. ArkSim Workflow ArkSim Workflow ## Who is it for? Developers looking to ensure their agents are robust, reliable, and ready for real-world interactions, without relying on manual testing. ## What makes it different? Fully transparent and customizable, letting you extend or adapt the tool as needed. Test your agent in realistic scenarios to uncover gaps in behavior or reliability before production. Use predefined scenarios to quickly validate your agent and jump-start testing effectively. Integrate with existing systems and tailor the testing environment to your specific needs. ## Core Capabilities ### Scenarios A scenario is a test case that defines a simulated user’s attributes, goals, and prior knowledge. It allows you to test different versions of your agent against the same set of scenarios to compare behavior and catch regressions. ### Simulation Simulation turns scenarios into live, multi-turn conversations with your agent. You get full transcripts (and optional metadata) that you can critically inspect or pass to evaluation. ### Evaluation Evaluation scores your agent on those conversations. You get quantitative and qualitative metrics (e.g. helpfulness, faithfulness) and agent behavior failures that you can prioritize and fix. ## Frequently Asked Questions ArkSim generates realistic multi-turn conversations between LLM-powered synthetic users and your agent, then evaluates every turn. Each synthetic user has a distinct profile, goal, and knowledge level. This reveals failures that only emerge across multiple conversation turns, like losing context, calling the wrong tool, or contradicting earlier responses. Install with `pip install arksim`, run `arksim init` to scaffold a starter config and agent file, then run `arksim simulate-evaluate config.yaml`. See the [quickstart guide](./quickstart) for a full walkthrough. ArkSim works with any AI agent, whether it is built with LangChain, CrewAI, OpenAI Agents SDK, or your own custom code. Connect through a Chat Completions HTTP endpoint, the A2A protocol, or load a Python agent class directly with no server needed. See the full list of [supported integrations](./integrations). Yes. ArkSim runs as a CLI command that exits non-zero when quality thresholds are not met. Add it to any CI pipeline as a quality gate on every pull request. See the [CI integration guide](./ci-integration). Built-in metrics include helpfulness, coherence, relevance, faithfulness, verbosity, goal completion, and agent behavior failure detection. You can also define custom quantitative and qualitative metrics with full access to the conversation context. See the [evaluation guide](./evaluate-conversation). ## Ready to start? Test your AI agent with ArkSim. Follow the quick start or explore the source on GitHub. Set up your first simulation in minutes. Explore full implementation on GitHub. # Personal AI Assistant (OpenClaw) Source: https://docs.arklex.ai/v0.3.x/personal-ai-assistant-openclaw-evaluation End-to-end example of using ArkSim to simulate and evaluate an OpenClaw personal AI assistant handling smart home, calendar, and messaging tasks. ## Overview This example walks through running ArkSim against an **OpenClaw** personal AI assistant. OpenClaw is an open-source assistant that runs on your own hardware and can manage tasks, smart home devices, messaging, calendar, and files. You use this setup to simulate and evaluate conversations against your own OpenClaw deployment. The agent is exposed via a Chat Completions-compatible endpoint; the example `config.yaml` is already configured for the OpenClaw gateway. *** ## Prerequisites Before getting started: * **OpenClaw** installed and configured: [openclaw.ai](https://openclaw.ai/) * **OpenClaw gateway** running with the HTTP Chat Completions endpoint enabled * **OpenAI API key**: used by ArkSim to power the simulated user * **OpenClaw gateway token**: for authenticating to your OpenClaw instance (see `~/.openclaw/openclaw.json` under `gateway.auth.token`) *** ## Scenarios The example ships with pre-built scenarios in `scenarios.json` representing realistic interactions with a personal AI assistant. Each scenario defines a simulated user with a distinct persona, goal, and background knowledge (files, smart home setup, contacts, tasks, etc.). The scenario goals are: * Manage reminders and to-do lists for files and storage (cleanup Downloads, cloud folders, storage alerts, important documents). * Control and automate smart home devices and scenes (lights, thermostat, blinds, locks, scenes like Good Morning, Movie Night, Leaving Home, Goodnight). * Send and manage messages across WhatsApp, iMessage, Slack, email, and Telegram using contacts and recent conversations. * Manage calendar and schedule (e.g. call dentist to confirm appointment, schedule car maintenance, recurring reminders, upcoming tasks). * Organize files and documents across local folders and cloud storage (cleanup Downloads, duplicate photos, Trash, important items and shared folders). Scenarios are defined in `scenarios.json` in the example directory and can be edited or extended to reflect your assistant's capabilities. *** ## Setup In `~/.openclaw/openclaw.json`, enable the HTTP Chat Completions endpoint: ```json theme={null} { "gateway": { "http": { "endpoints": { "chatCompletions": { "enabled": true } } } } } ``` ```bash theme={null} openclaw gateway --port 18789 --verbose ``` ```bash theme={null} export OPENAI_API_KEY="" export OPENCLAW_TOKEN="" ``` Your gateway token is in `~/.openclaw/openclaw.json` under `gateway.auth.token`. Before running simulation, confirm the gateway is responding: ```bash theme={null} curl -sS "http://127.0.0.1:18789/v1/chat/completions" \ -H "Authorization: Bearer $OPENCLAW_TOKEN" \ -H "Content-Type: application/json" \ -H "x-openclaw-agent-id: main" \ -d '{"model":"openclaw","messages":[{"role":"user","content":"Hello"}]}' ``` You should receive a valid JSON response from the gateway. Run from the `examples/openclaw` directory: ```bash theme={null} cd examples/openclaw arksim simulate-evaluate config.yaml ``` The `config.yaml` has the `agent_config` pointed at `http://localhost:18789/v1/chat/completions` with `Authorization: Bearer ${OPENCLAW_TOKEN}` and `x-openclaw-agent-id: main`. *** ## Configuration The example uses a single config file for both simulation and evaluation. Agent configuration is specified inline under the `agent_config` key: ```yaml theme={null} # AGENT CONFIGURATION agent_config: agent_type: chat_completions agent_name: openclaw api_config: endpoint: http://localhost:18789/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENCLAW_TOKEN}" x-openclaw-agent-id: main body: model: openclaw messages: - role: system content: "You are a helpful personal assistant." enable_metadata: false # SIMULATION SETTINGS # Path to the scenarios file scenario_file_path: ./scenarios.json # Number of conversations per scenario to generate num_conversations_per_scenario: 1 # Maximum turns per conversation max_turns: 5 # Output file path for simulation results output_file_path: ./results/simulation/simulation.json # Jinja template for the simulated user's system prompt simulated_user_prompt_template: null # EVALUATION SETTINGS # Output directory for evaluation results output_dir: ./results/evaluation # Paths to Python files defining custom # QuantitativeMetric or QualitativeMetric subclasses custom_metrics_file_paths: [] # Built-in metrics to run; if empty, all built-in metrics run metrics_to_run: - faithfulness - helpfulness - coherence - verbosity - relevance - goal_completion - agent_behavior_failure # Generate HTML report generate_html_report: true # Numeric thresholds: per-metric minimum scores on native scale # numeric_thresholds: # overall_score: 0.7 # goal_completion: 0.6 # SHARED SETTINGS # LLM model model: gpt-5.1 # LLM provider provider: openai # Workers for parallel processing num_workers: 50 ``` *** ## Output Results are written under the example directory: | Location | Contents | | ---------------------------------------- | ------------------------------------------------------------------------ | | `./results/simulation/simulation.json` | Simulated conversations from the simulation step | | `./results/evaluation/evaluation.json` | Evaluation results (per-turn and per-conversation scores, unique errors) | | `./results/evaluation/final_report.html` | Interactive HTML report for browsing and sharing results | *** ## Example Files | File | Description | | ---------------- | ---------------------------------------------------------------------- | | `config.yaml` | Simulate and evaluate configuration with inline OpenClaw agent config. | | `scenarios.json` | Pre-built scenarios for the personal assistant. | *** ## Adapting to Your Own Assistant To use this example as a starting point for your own personal assistant: 1. **Scenarios**: Edit or add scenarios in `scenarios.json` so goals and knowledge reflect your assistant's capabilities. 2. **Agent config**: If your endpoint, port, or auth headers differ from the OpenClaw defaults, update the `agent_config` section within `config.yaml` file accordingly. See [Agent configuration](./simulate-conversation#agent-configuration) for supported protocols and how to configure agent connections. # Quickstart Source: https://docs.arklex.ai/v0.3.x/quickstart Get started with ArkSim in minutes. Test your own agent or explore a pre-built example with a single command. ## Prerequisites * Python 3.10-3.13 * An API key from a supported provider ([OpenAI](https://developers.openai.com/api/docs), [Anthropic](https://platform.claude.com/docs/en/home), or [Google Gemini](https://ai.google.dev/gemini-api/docs/api-key)) ## Option A: Test your own agent If you already have an agent running, use `arksim init` to scaffold a starter config and scenarios file, then point it at your endpoint. ```bash theme={null} pip install arksim export OPENAI_API_KEY="your-api-key" ``` For other providers: `pip install "arksim[anthropic]"` or `pip install "arksim[google]"`. ```bash theme={null} arksim init ``` This creates three files in the current directory: * **config.yaml** pointing at `./my_agent.py` with sensible defaults * **scenarios.json** with four domain-agnostic starter scenarios (happy path, out of scope, ambiguous intent, multi-step) * **my\_agent.py** with a `BaseAgent` subclass ready to fill in (no server needed) Open `my_agent.py` and replace the `execute()` body with your agent logic. All files include inline comments explaining each field. For HTTP or A2A agents, use `arksim init --agent-type chat_completions` or `arksim init --agent-type a2a` instead. Use `--force` to re-scaffold if files already exist. ```bash theme={null} arksim simulate-evaluate config.yaml ``` Open `results/final_report.html` in your browser for an interactive report with scores, failure categories, and full conversation transcripts. ## Option B: Explore a pre-built example If you want to see ArkSim in action before connecting your own agent, try one of the included examples. ```bash theme={null} pip install arksim export OPENAI_API_KEY="your-api-key" ``` ```bash theme={null} arksim examples ``` This creates an `examples/` folder with ready-to-run projects (bank-insurance, e-commerce, customer-service, openclaw). ```bash theme={null} cd examples/bank-insurance arksim simulate-evaluate config.yaml ``` ```python theme={null} import asyncio from arksim.simulation_engine import run_simulation, SimulationInput from arksim.evaluator import run_evaluation, EvaluationInput from arksim.config import AgentConfig from arksim.scenario import Scenarios EXAMPLE_DIR = "./examples/bank-insurance" agent_config = AgentConfig( agent_type="chat_completions", agent_name="bank-insurance", api_config={ "endpoint": "https://api.openai.com/v1/chat/completions", "headers": { "Content-Type": "application/json", "Authorization": "Bearer ${OPENAI_API_KEY}", }, "body": { "model": "gpt-5.1", "messages": [ {"role": "system", "content": "You are a customer service chatbot for XYZ Bank insurance."} ], }, }, ) scenarios = Scenarios.load(f"{EXAMPLE_DIR}/scenarios.json") simulation = asyncio.run(run_simulation(SimulationInput( agent_config=agent_config, num_conversations_per_scenario=1, max_turns=5, num_workers="50", output_file_path=f"{EXAMPLE_DIR}/results/simulation.json", ))) evaluation = run_evaluation(EvaluationInput( scenario_file_path=f"{EXAMPLE_DIR}/scenarios.json", output_dir=f"{EXAMPLE_DIR}/results", custom_metrics_file_paths=[f"{EXAMPLE_DIR}/custom_metrics.py"], metrics_to_run=[ "faithfulness", "helpfulness", "coherence", "relevance", "goal_completion", "agent_behavior_failure", ], model="gpt-5.1", provider="openai", num_workers=50, generate_html_report=True, ), simulation=simulation, scenarios=scenarios) print(f"Done. Simulated {len(simulation.conversations)} conversations.") ``` ```bash theme={null} arksim ui ``` Opens at [**http://localhost:8080**](http://localhost:8080). Load any example config and run from the browser. Open `results/evaluation/final_report.html` in your browser for scores, failure analysis, and full conversation transcripts. ### Using other LLM providers ArkSim uses OpenAI by default for both the simulated user and the evaluator. To use Anthropic or Google instead, set the provider in your `config.yaml`: ```bash theme={null} pip install "arksim[anthropic]" export ANTHROPIC_API_KEY="your-api-key" ``` ```yaml theme={null} model: claude-opus-4-6 provider: anthropic ``` ```bash theme={null} pip install "arksim[google]" export GEMINI_API_KEY="your-api-key" ``` ```yaml theme={null} model: gemini-2.5-flash provider: google ``` *** ## Next Steps Now that you've run your first simulation and evaluation, here's where to go next. * **Explore the core concepts:** Dive deeper into [Scenarios](./build-scenario), [Simulation](./simulate-conversation), and [Evaluation](./evaluate-conversation) to understand how each piece works and how to configure them for your agent. * **Explore the examples:** Run ArkSim against [E-commerce](./e-commerce-customer-service-agent-evaluation), [Insurance](./insurance-customer-service-agent-evaluation), [Customer Service (tool calling)](./customer-service-tool-calling-agent-evaluation), and [Personal AI assistant (OpenClaw)](./personal-ai-assistant-openclaw-evaluation) to see different use cases and configs. # Schema Reference Source: https://docs.arklex.ai/v0.3.x/schema-reference JSON and YAML schemas used by ArkSim for scenarios, simulation output, evaluation output, and run configuration. This page documents the structure of the main artifacts used and produced by ArkSim: scenario files, simulation output, evaluation output, and the run configuration file. Use it when building integrations, writing custom tooling, or debugging pipeline outputs. For agent connection details (Chat Completions, A2A, and config), see [Agent configuration](./simulate-conversation#agent-configuration). *** ## Scenarios (`scenarios.json`) The scenario file is a single JSON document that lists scenario objects. Each scenario describes one simulated user and one conversation session. It is the input to [Simulation](./simulate-conversation) and is referenced during [Evaluation](./evaluate-conversation). ### Schema Schema version identifier. Use `"v1"`. List of scenario objects. Unique identifier for this scenario. Unique identifier for the simulated user. The user's conversational goal, passed into the simulated user prompt. Write in second person ("You want to..."). Context about the agent (e.g. company or product overview) supplied to the simulated user. Natural-language persona description for the simulated user. Used directly in the simulation prompt. Write in second person ("You are..."). Knowledge items injected into the simulated user's context. Can be an empty list. Each item has: * `content` (string, required): Text used as the user's background knowledge. (Additional keys such as `metadata` may be present in the file for traceability but are not part of the loaded model.) Provenance metadata (e.g. `target_agent_capability`, `goal_raw`, `user_attributes`). Not used by the simulator or evaluator. *** ## Simulation output (`simulation.json`) Written by `arksim simulate` or the simulation step of `arksim simulate-evaluate`. Path is set by `output_file_path` in your config. ### Schema Output schema version (e.g. `"v1"`). ArkSim package version that produced this file. UUID that uniquely identifies this simulation run. Referenced by the evaluation output as `simulation_id` to link the two artifacts. ISO-8601 UTC timestamp when the file was generated. One record per simulated conversation. Unique ID for this conversation. ID of the scenario used for this conversation. Ordered list of messages in the conversation. Each message has: `turn_id` (int), `message_id` (string), `role` (`"simulated_user"` or `"assistant"`), `content` (string). Rendered simulated user prompt and variables used to drive the conversation. * `simulated_user_prompt_template`: The Jinja template used for the simulated user system prompt. * `variables`: Dict used to render the template. Keys are `scenario.agent_context`, `scenario.goal`, `scenario.knowledge`, and `scenario.user_profile`. *** ## Evaluation output (`evaluation.json`) Written by `arksim evaluate` or the evaluation step of `arksim simulate-evaluate`. Path is `{output_dir}/evaluation.json`. ### Schema Output schema version (e.g. `"v1.1"`). ISO-8601 UTC timestamp when the file was generated. ArkSim package version that produced this file. UUID that uniquely identifies this evaluation run. Generated fresh for each `arksim evaluate` or `arksim simulate-evaluate` invocation. UUID of the simulation run that produced the conversations being evaluated. Copied from `simulation.json` to link the two artifacts. One record per conversation evaluated. ID of the conversation. How fully the user goal was achieved (0–1). Explanation for the goal completion score. Proportion of turns with no detected behavior failure (0–1). Combined score for the conversation (0–1). Computed from turn\_success\_ratio and goal\_completion\_score. One of: `completed`, `partial_failure`, `failed`. Per-turn scores and failure labels. Each turn has: `turn_id`, `scores` (list of metric results with `name`, `value`, optional `reason`, optional `metadata`), `turn_score`, `turn_behavior_failure`, `turn_behavior_failure_reason`, `qual_scores`, `unique_error_ids`. Deduplicated behavior failures across all conversations. Unique ID (e.g. UUID) for this error pattern. Category of the failure (e.g. lack of specific information, repetition, false information). Human-readable description of the error. Default `"medium"`. Severity of the error. List of (conversation\_id, turn\_id) where this error occurred. Maps each unique error to the scenarios that triggered it. Empty when no errors are detected or no scenario file was provided. Added in schema version `v1.1`. Position in the list, ordered by severity (1 = most severe) then by occurrence count. Links to the matching entry in `unique_errors`. Human-readable description of the error. `critical`, `high`, `medium`, or `low`. IDs of scenarios that triggered this error, sorted alphabetically. *** ## Focus files (`focus/error_N.json`, `focus/all_failures.json`) Written to `{output_dir}/focus/` when unique errors are detected and a scenario file is provided. Each file uses the standard [Scenario input](#scenarios-scenariosjson) schema. Copied from the original scenario file (e.g. `"v1"`). Filtered subset of the original scenarios. For `error_N.json`, only scenarios that triggered error group N. For `all_failures.json`, the union of all failing scenarios (deduplicated). Files are numbered by severity (1 = highest) then by occurrence count. See [Focus Files](./evaluate-conversation#focus-files) for usage. *** ## Run configuration (`config.yaml`) The same YAML file can be used for `arksim simulate`, `arksim evaluate`, and `arksim simulate-evaluate`. For `simulate-evaluate`, simulation and evaluation settings are merged from a single config. ### Agent configuration | Key | Type | Description | | -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ | | `agent_config` | object | Inline agent configuration. See [Agent configuration](./simulate-conversation#agent-configuration) for `chat_completions` and `a2a`. | ### Simulation keys Used by `simulate` and the simulation phase of `simulate-evaluate`. | Key | Type | Description | | -------------------------------- | ------------- | -------------------------------------------------------------- | | `scenario_file_path` | string | Path to `scenarios.json`. | | `num_conversations_per_scenario` | int | Number of conversations to run per scenario. | | `max_turns` | int | Maximum turns per conversation. | | `output_file_path` | string | Path where `simulation.json` is written. | | `simulated_user_prompt_template` | string | Optional. Jinja template for the simulated user system prompt. | | `model` | string | LLM model (e.g. `gpt-5.1`). | | `provider` | string | LLM provider (e.g. `openai`). | | `num_workers` | string \| int | Parallel workers (default `50`). Set `"auto"` to auto-scale. | ### Evaluation keys Used by `evaluate` and the evaluation phase of `simulate-evaluate`. | Key | Type | Description | | ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scenario_file_path` | string | Path to `scenarios.json` (for goal and knowledge during evaluation). | | `simulation_file_path` | string | Path to simulation output (`simulation.json`). Omitted when running `simulate-evaluate` (output passed in memory). | | `output_dir` | string | Directory for evaluation results; `evaluation.json` and optional reports are written here. | | `custom_metrics_file_paths` | list\[string] | Paths to Python files defining custom metrics. | | `metrics_to_run` | list\[string] | Names of built-in metrics to run. If empty, all built-in metrics run. | | `generate_html_report` | boolean | Whether to generate `final_report.html`. | | `numeric_thresholds` | dict\[string, float] \| null | Per-metric thresholds on each metric's native scale. Keys are metric names; values are minimum required scores. Built-in turn-level metrics use a 1–5 scale (mean across turns per conversation). `goal_completion` and `overall_score` use 0–1 and are compared directly. | | `qualitative_failure_labels` | dict\[string, list\[string]] \| null | Hard-gate failure labels for qualitative metrics. Keys are metric names; values are lists of labels that trigger failure (e.g. `agent_behavior_failure: ["false information", "disobey user request"]`). Any evaluated turn whose label appears in the list fails the run with exit code 1. | | `model` | string | LLM model for scoring. | | `provider` | string | LLM provider. | | `num_workers` | string \| int | Parallel workers (default `50`). Set `"auto"` to auto-scale. | `model`, `provider`, and `num_workers` are shared across simulation and evaluation when both run from the same config. *** ## Exit codes The `arksim` CLI exits with one of the following codes, suitable for use in CI/CD pipelines: | Code | Constant | When it is returned | | ---- | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | `0` | `EXIT_OK` | Run completed successfully and all threshold checks passed. | | `1` | `EXIT_EVAL_FAILED` | Evaluation completed but one or more threshold checks failed (`numeric_thresholds` or `qualitative_failure_labels`). | | `2` | `EXIT_CONFIG_ERROR` | Invalid or missing configuration (bad YAML, unknown keys, missing required fields). | | `3` | `EXIT_INTERNAL_ERROR` | Unexpected internal error. | # Simulation Source: https://docs.arklex.ai/v0.3.x/simulate-conversation Run ArkSim scenarios as live multi-turn conversations against your agent and collect transcripts for evaluation. ## What is Simulation? Simulation is the process where ArkSim runs your pre-built scenarios as live conversations against your agent. Each scenario acts as a simulated user with a defined persona, goal, and prior knowledge who drives a multi-turn interaction with the agent until the user's goal is achieved or the turn limit is reached. The **output** is a set of conversation transcripts you can inspect directly or pass into Evaluation. ArkSim Simulation Workflow *** ## Inputs Before running a simulation, you need three things in place: | Input | Description | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | **Scenarios** | A `scenarios.json` file defining user attributes, goals, knowledge, and scenario metadata. [Learn how to write scenarios →](./build-scenario) | | **Agent config** | Inline `agent_config` in your config YAML. Defines how ArkSim connects to your agent. See [Agent configuration](#agent-configuration) below. | | **Config file** | `config.yaml` controlling simulation parameters such as number of conversations, max turns, workers, and model settings. | *** ## Configuration ```yaml theme={null} # Agent configuration agent_config: agent_type: chat_completions agent_name: my-agent api_config: endpoint: https://api.openai.com/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENAI_API_KEY}" body: model: gpt-5.1 messages: - role: system content: "You are a helpful assistant." # Scenario input scenario_file_path: ./scenarios.json # Simulation parameters num_conversations_per_scenario: 5 # Number of conversations per scenario max_turns: 5 # Maximum turns per conversation num_workers: 50 # Parallel workers # Output output_file_path: ./simulation.json # Model configuration (used for the simulated user, not your agent) model: gpt-5.1 provider: openai # Optional: custom Jinja2 template for the simulated user prompt # simulated_user_prompt_template: null ``` The default `num_workers` is `50`. Set `num_workers: auto` to automatically parallelize across all conversations, or specify a fixed number to control load on your agent endpoint. ### Advanced: Custom simulated user prompt By default, ArkSim uses a built-in system prompt to drive the simulated user. You can override it by setting `simulated_user_prompt_template` in your config to a **Jinja2** template string. The template is rendered per conversation with these variables: **From the scenario file** * **`scenario.agent_context`**: A description of the agent being simulated against (e.g., its role, domain, or business purpose). * **`scenario.goal`**: The specific task or objective the simulated user is trying to accomplish during the conversation (e.g., "file an insurance claim"). * **`scenario.knowledge`**: Reference content (e.g., product details, policy documents) that the simulated user can draw on when answering or asking questions. * **`scenario.user_profile`**: A second-person natural language persona description for the simulated user, used as-is in the prompt. Use them in your template with `{{ scenario.goal }}`, `{{ scenario.user_profile }}`, and so on. If you omit `simulated_user_prompt_template`, the default prompt is used. The built-in template used when `simulated_user_prompt_template` is not set: ```jinja2 theme={null} You are a user interacting with an agent through multiple turns. The agent is supplied by the following conversation context: {{ scenario.agent_context }} Your profile is: {{ scenario.user_profile }} You have the following goal when interacting with this agent: {{ scenario.goal }} {% if scenario.knowledge and scenario.knowledge|length == 1 %} Here is the content that you might be interested in and might have questions about: {{ scenario.knowledge[0].content }} {% elif scenario.knowledge and scenario.knowledge|length > 1 %} You will receive reference knowledge in a user message immediately before each of your replies; use it when relevant to achieve your goal. {% endif %} Rules: - Do not give away all the instruction at once. Only provide the information necessary for the current step. - Do not hallucinate information that is not provided in the instruction. - If the instruction goal is satisfied, generate '###STOP###' as a standalone message without anything else. - Do not repeat the exact instruction in the conversation. - Avoid using bullet points or lists. - Keep responses brief and under 50 words. - You are the user and the agent is the assistant. Do not flip the roles. {% if scenario.knowledge and scenario.knowledge|length > 1 %} - Ask only one question per turn. {% endif %} ``` *** ## Agent configuration Provide agent connection by defining `agent_config` inline in your config YAML. ### Configuration fields | Field | Type | Required | Description | | --------------- | ------ | ----------- | ----------------------------------------------------------------------------------------- | | `agent_name` | string | Yes | Unique identifier for your agent (e.g. lowercase, no spaces). | | `agent_type` | string | Yes | One of `chat_completions`, `a2a`, or `custom`. See [Connection types](#connection-types). | | `api_config` | object | Conditional | Required for `chat_completions` and `a2a`. See [Connection types](#connection-types). | | `custom_config` | object | Conditional | Required for `custom`. See [Connection types](#connection-types). | ### Connection types ArkSim supports three ways to connect your agent: | Type | When to use | | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | [**Chat Completions**](https://developers.openai.com/api/reference/resources/chat/) | Any agent that accepts OpenAI-compatible requests (OpenAI or a custom wrapper) | | [**A2A**](https://a2a-protocol.org/latest/) | Agents exposed via the Agent-to-Agent protocol | | **Custom** | Any Python agent loaded directly as a class — no HTTP server required | **Type:** `chat_completions` Connects to any OpenAI-compatible chat completions endpoint. **Required fields:** `endpoint` (API URL), `headers` (e.g. `Content-Type`; `Authorization` optional), `body` (must include a `messages` array). **Placeholders:** `${ENV_VAR}` is supported in header values for secrets. **Example (YAML):** ```yaml theme={null} agent_config: agent_type: chat_completions agent_name: my-agent api_config: endpoint: https://api.openai.com/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENAI_API_KEY}" body: model: gpt-5.1 messages: - role: system content: "You are a helpful assistant." ``` **Type:** `a2a` For agents that speak the Agent-to-Agent (A2A) protocol. **Required fields:** `endpoint` (A2A agent server URL). **Optional:** `headers` (e.g. for auth). **Example (YAML):** ```yaml theme={null} agent_config: agent_type: a2a agent_name: a2a-agent api_config: endpoint: http://localhost:9999 headers: api-key: "${A2A_AUTH_TOKEN}" ``` **Type:** `custom` Loads your agent directly as a Python class — no HTTP server needed. Your agent must subclass `BaseAgent` and implement `get_chat_id()` and `execute()`. **Required fields:** `module_path` (path to a `.py` file containing your `BaseAgent` subclass). **Optional:** `class_name` (if the file contains multiple `BaseAgent` subclasses). **Example agent (`my_agent.py`):** ```python theme={null} from arksim.config import AgentConfig from arksim.simulation_engine.agent.base import BaseAgent class MyAgent(BaseAgent): def __init__(self, agent_config: AgentConfig) -> None: super().__init__(agent_config) async def get_chat_id(self) -> str: return "unique-conversation-id" async def execute(self, user_query: str, **kwargs: object) -> str: return "agent response" ``` **Example (YAML):** ```yaml theme={null} agent_config: agent_type: custom agent_name: my-agent custom_config: module_path: ./my_agent.py ``` **Example (Python — no YAML needed):** ```python theme={null} from arksim.config import AgentConfig, CustomConfig from my_agent import MyAgent agent_config = AgentConfig( agent_type="custom", agent_name=MyAgent.__name__, custom_config=CustomConfig(agent_class=MyAgent), ) ``` ### Environment variable support Both types support `${ENV_VAR}` substitution in header values (and in the endpoint URL for chat completions where applicable). At runtime the value is replaced; if unset, it becomes an empty string. You can mix static text and variables (e.g. `"Bearer ${API_KEY}"`). **Security:** Keep credentials in environment variables and out of committed config files. *** ## Running a Simulation Create a `config.yaml` file with your agent config and simulation parameters: ```yaml theme={null} agent_config: agent_type: chat_completions agent_name: my-agent api_config: endpoint: https://api.openai.com/v1/chat/completions headers: Content-Type: application/json Authorization: "Bearer ${OPENAI_API_KEY}" body: model: gpt-5.1 messages: - role: system content: "You are a helpful assistant." scenario_file_path: ./scenarios.json num_conversations_per_scenario: 5 max_turns: 5 num_workers: 50 output_file_path: ./simulation.json model: gpt-5.1 provider: openai ``` Run a simulation with the default configuration: ```bash theme={null} arksim simulate config.yaml ``` You can override config values with CLI flags: ```bash theme={null} arksim simulate config.yaml --max-turns 10 --num-workers 4 ``` ```python theme={null} import asyncio from arksim.simulation_engine import run_simulation, SimulationInput from arksim.config import AgentConfig agent_config = AgentConfig( agent_type="chat_completions", agent_name="my-agent", api_config={ "endpoint": "https://api.openai.com/v1/chat/completions", "headers": { "Content-Type": "application/json", "Authorization": "Bearer ${OPENAI_API_KEY}", }, "body": { "model": "gpt-5.1", "messages": [ {"role": "system", "content": "You are a helpful assistant."} ], }, }, ) simulation = asyncio.run(run_simulation(SimulationInput( agent_config=agent_config, scenario_file_path="./scenarios.json", num_conversations_per_scenario=1, max_turns=10, num_workers=50, output_file_path="./simulation.json", ))) ``` Simulation writes to the path set by `output_file_path` (default `./simulation.json`). The file contains the full transcript of every conversation, ready to inspect or pass into [Evaluation](./evaluate-conversation). *** ## Output Simulation writes one file: the path set by `output_file_path` (default `./simulation.json`). It contains the full transcript of every conversation: message history, scenario ID, simulated user prompt (template and variables), and all agent and simulated user messages. For the full structure and field order, see the [Schema Reference](./schema-reference#simulation-output-simulation-json). ### Example output ```json theme={null} { "schema_version": "v1", "simulator_version": "v1", "simulation_id": "a3f2c1d4-8e7b-4f9a-b6c2-1d0e5f3a8b7c", "generated_at": "2025-04-10T14:32:00Z", "conversations": [ { "conversation_id": "00de685e-f76b-4a5f-a6e5-217cad777316", "scenario_id": "8f4c2a91-3b7e-4d5f-a9c2-6e1b4d9f2037", "conversation_history": [ { "turn_id": 0, "message_id": "3c9a7f12-6b4e-4d8a-b2f1-9e5c0a7d41e6", "role": "simulated_user", "content": "So this whole identity theft thing is stressing me out a bit...." }, { "turn_id": 0, "message_id": "b7e2c9a4-1f6d-4c83-9a5b-2d8e7f0c4a91", "role": "assistant", "content": "I understand your concern about identity theft, but rest assured..." } ], "simulated_user_prompt": { "simulated_user_prompt_template": "You are a customer interacting with an agent through multiple turns...", "variables": { "scenario.agent_context": "XYZ Bank Insurance is a Canadian provider of...", "scenario.user_profile": "You are Priya Sharma, a 32-year-old from Toronto, ON...", "scenario.goal": "You want to find out what documents are needed...", "scenario.knowledge": ["Typical timelines: claim setup is usually same day..."] } } } ] } ``` *** ## Next Steps Once your conversations are simulated, you're ready to evaluate how well your agent performed. Score your agent's responses against the simulated user's goals and knowledge.