diff --git a/.github/workflows/config/.secrets.baseline b/.github/workflows/config/.secrets.baseline
index 4421169de1..680e29e9bd 100644
--- a/.github/workflows/config/.secrets.baseline
+++ b/.github/workflows/config/.secrets.baseline
@@ -133,6 +133,43 @@
}
],
"results": {
+ "resources_servers/enterpriseops_gym/data/tools/drive.json": [
+ {
+ "type": "Base64 High Entropy String",
+ "filename": "resources_servers/enterpriseops_gym/data/tools/drive.json",
+ "hashed_secret": "bd5a04fa3667e693edc13239b6d310c5c7a8564b",
+ "is_verified": false,
+ "line_number": 277
+ },
+ {
+ "type": "Base64 High Entropy String",
+ "filename": "resources_servers/enterpriseops_gym/data/tools/drive.json",
+ "hashed_secret": "abf30b61772a936ff7d19e68390710cc08706a08",
+ "is_verified": false,
+ "line_number": 391
+ },
+ {
+ "type": "Base64 High Entropy String",
+ "filename": "resources_servers/enterpriseops_gym/data/tools/drive.json",
+ "hashed_secret": "ebc6f5311d10c5014dc4c891846eb78e893936a6",
+ "is_verified": false,
+ "line_number": 1569
+ },
+ {
+ "type": "Base64 High Entropy String",
+ "filename": "resources_servers/enterpriseops_gym/data/tools/drive.json",
+ "hashed_secret": "e311b841fe7756bd3956a94f986f3197def5e4b4",
+ "is_verified": false,
+ "line_number": 1603
+ },
+ {
+ "type": "Base64 High Entropy String",
+ "filename": "resources_servers/enterpriseops_gym/data/tools/drive.json",
+ "hashed_secret": "d1914cf8ee03de23b2b8164b7d6ef8f897eb2815",
+ "is_verified": false,
+ "line_number": 2752
+ }
+ ],
"responses_api_agents/pinchbench/tests/test_app.py": [
{
"type": "Secret Keyword",
@@ -157,5 +194,5 @@
}
]
},
- "generated_at": "2026-07-10T07:53:12Z"
+ "generated_at": "2026-07-27T00:42:56Z"
}
diff --git a/README.md b/README.md
index 9a56b87fbd..892f95a871 100644
--- a/README.md
+++ b/README.md
@@ -218,6 +218,8 @@ The Dataset column links to publicly available datasets (e.g., on HuggingFace).
| Code Gen | coding | Model must submit the right code to solve a problem | Improve competitive coding capabilities | ✓ | ✓ | Apache 2.0 | code_gen.yaml | nemotron-RL-coding-competitive_coding |
| Competitive Coding Challenges | coding | Execution of competitive programming competition questions | Improve competitive coding capabilities on contest-style problems | - | - | - | competitive_coding_challenges.yaml | - |
| Critpt | other | Research-level physics problems scored by the Artificial Analysis API | Evaluate model performance on research-level physics reasoning | - | - | - | critpt.yaml | - |
+| Enterpriseops Gym | agent | EnterpriseOps-Gym benchmark with per-turn telemetry logging (timings, token usage incl. cache hits, tool latencies) | Improve stateful multi-step enterprise planning and tool use | - | - | - | enterpriseops_gym_turnlog.yaml | - |
+| Enterpriseops Gym | agent | EnterpriseOps-Gym enterprise tool-use benchmark (external MCP gym servers + SQL/judge verifiers) | Improve stateful multi-step enterprise planning and tool use | - | - | - | enterpriseops_gym.yaml | - |
| Equivalence Llm Judge | agent | Short bash command generation questions with LLM-as-a-judge | Improve foundational bash and IF capabilities | ✓ | ✓ | GNU General Public License v3.0 | nl2bash-equivalency.yaml | - |
| Equivalence Llm Judge | knowledge | Short answer questions with LLM-as-a-judge | Improve knowledge-related benchmarks like GPQA / HLE | - | - | - | equivalence_llm_judge.yaml | - |
| Equivalence Rule | knowledge | Question - Answering with rule-based reward | Improve retrieval and counting capabilities | - | - | - | lc.yaml | - |
diff --git a/benchmarks/enterpriseops/README.md b/benchmarks/enterpriseops/README.md
new file mode 100644
index 0000000000..1487acf60b
--- /dev/null
+++ b/benchmarks/enterpriseops/README.md
@@ -0,0 +1,32 @@
+# EnterpriseOps-Gym Benchmark
+
+Oracle-mode public split of [ServiceNow EnterpriseOps-Gym](https://github.com/ServiceNow/EnterpriseOps-Gym)
+(Apache 2.0): stateful enterprise tool-use tasks across 8 domains (Calendar, CSM, Drive, Email,
+HR, ITSM, Teams, Hybrid), graded by SQL verifiers on final database state. See
+`resources_servers/enterpriseops_gym/README.md` for architecture and parity notes.
+
+## Prerequisites
+
+1. The upstream MCP gym Docker containers running (7 domain servers; see the resources
+ server README for ports) and the EOG checkout with `gym_dbs.zip` unzipped
+ (`seed_sql_root` config).
+2. Hub egress at prepare time (`huggingface.co`). On machines without egress, set
+ `NEMO_GYM_EOG_LOCAL_TASKS=/data/revised` to convert the locally
+ committed task subset instead.
+
+## Usage
+
+```bash
+ng_prepare_benchmark "+config_paths=[benchmarks/enterpriseops/config.yaml]"
+
+ng_run "+config_paths=[benchmarks/enterpriseops/config.yaml,responses_api_models/openai_model/configs/openai_model.yaml]" \
+ "++enterpriseops_benchmark_resources_server.resources_servers.enterpriseops_gym.seed_sql_root="
+
+ng_collect_rollouts +agent_name=enterpriseops_benchmark_simple_agent \
+ +input_jsonl_fpath=benchmarks/enterpriseops/data/enterpriseops_oracle_benchmark.jsonl \
+ +output_jsonl_fpath=results/enterpriseops_oracle.jsonl
+```
+
+Scoring: `reward` = EOG leaderboard parity (all name-collapsed verifiers pass). Aggregate
+metrics include per-domain `{domain}/success_rate`, `{domain}/verifier_pass_rate`, and
+`macro_success_rate` (mean over domains, the leaderboard "Avg").
diff --git a/benchmarks/enterpriseops/__init__.py b/benchmarks/enterpriseops/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/benchmarks/enterpriseops/config.yaml b/benchmarks/enterpriseops/config.yaml
new file mode 100644
index 0000000000..54b1aa3278
--- /dev/null
+++ b/benchmarks/enterpriseops/config.yaml
@@ -0,0 +1,24 @@
+# Chain to the EnterpriseOps-Gym resources server + agent config
+config_paths:
+ - resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml
+
+# `_inherit_from` keeps this benchmark config isolated from the generic config above.
+enterpriseops_benchmark_resources_server:
+ _inherit_from: enterpriseops_gym
+
+enterpriseops_benchmark_simple_agent:
+ _inherit_from: enterpriseops_gym_simple_agent
+ responses_api_agents:
+ simple_agent:
+ resources_server:
+ name: enterpriseops_benchmark_resources_server
+ datasets:
+ - name: enterpriseops
+ type: benchmark
+ jsonl_fpath: benchmarks/enterpriseops/data/enterpriseops_oracle_benchmark.jsonl
+ prepare_script: benchmarks/enterpriseops/prepare.py
+ # Rows are fully materialized by the converter (system+user input, tools baked in),
+ # so no prompt templating applies.
+ prompt_config: null
+ # EOG leaderboard reports single-run task success; raise for mean@k.
+ num_repeats: 1
diff --git a/benchmarks/enterpriseops/data/.gitignore b/benchmarks/enterpriseops/data/.gitignore
new file mode 100644
index 0000000000..2fb4e2d9b7
--- /dev/null
+++ b/benchmarks/enterpriseops/data/.gitignore
@@ -0,0 +1 @@
+*.jsonl
diff --git a/benchmarks/enterpriseops/prepare.py b/benchmarks/enterpriseops/prepare.py
new file mode 100644
index 0000000000..b516941c6d
--- /dev/null
+++ b/benchmarks/enterpriseops/prepare.py
@@ -0,0 +1,117 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Prepare the EnterpriseOps-Gym benchmark (oracle mode, public split).
+
+Downloads the ServiceNow-AI/EnterpriseOps-Gym HuggingFace dataset (config = tool-set mode,
+split = domain) and converts every domain — including hybrid — into one combined NeMo Gym
+JSONL, baking in tool schemas from the per-domain snapshots shipped with the
+enterpriseops_gym resources server (see snapshot_tools.py there).
+
+Requires:
+- Egress to huggingface.co. If the Hub is unreachable and NEMO_GYM_EOG_LOCAL_TASKS is set
+ to an EnterpriseOps-Gym checkout's task folder root (containing / task JSON
+ dirs, e.g. data/revised), those local tasks are converted instead as a fallback.
+- The MCP gym Docker containers only at RUN time, not at prepare time.
+"""
+
+import json
+import os
+from pathlib import Path
+from typing import Dict, List
+
+from resources_servers.enterpriseops_gym.convert_tasks import (
+ convert_task,
+ load_snapshots,
+ load_tasks_from_dir,
+ load_tasks_from_hf,
+)
+
+
+BENCHMARK_DIR = Path(__file__).parent
+DATA_DIR = BENCHMARK_DIR / "data"
+OUTPUT_FPATH = DATA_DIR / "enterpriseops_oracle_benchmark.jsonl"
+
+# Set NEMO_GYM_EOG_HF_DATASET to a local snapshot of the dataset repo on machines without
+# Hub egress (datasets.load_dataset accepts a local directory path in place of a repo id).
+HF_REPO_ID = os.getenv("NEMO_GYM_EOG_HF_DATASET", "ServiceNow-AI/EnterpriseOps-Gym")
+MODE = "oracle"
+DOMAINS = ["calendar", "csm", "drive", "email", "hr", "itsm", "teams", "hybrid"]
+
+SNAPSHOTS_DIR = BENCHMARK_DIR.parent.parent / "resources_servers" / "enterpriseops_gym" / "data" / "tools"
+# All 7 gym snapshots; hybrid tasks reference multiple gyms, so hybrid uses the full union.
+DOMAIN_SNAPSHOTS: Dict[str, List[str]] = {
+ "calendar": ["calendar.json"],
+ "csm": ["csm.json"],
+ "drive": ["drive.json"],
+ "email": ["email.json"],
+ "hr": ["hr.json"],
+ "itsm": ["itsm.json"],
+ "teams": ["teams.json"],
+ "hybrid": ["calendar.json", "csm.json", "drive.json", "email.json", "hr.json", "itsm.json", "teams.json"],
+}
+
+LOCAL_TASKS_ENV_VAR = "NEMO_GYM_EOG_LOCAL_TASKS"
+
+
+def _convert_domain(domain: str, tasks, out_file) -> int:
+ snapshot_paths = [SNAPSHOTS_DIR / name for name in DOMAIN_SNAPSHOTS[domain]]
+ gym_tools = load_snapshots(snapshot_paths)
+ num_written = 0
+ for task_id, task in tasks:
+ row = convert_task(task, task_id, domain, MODE, gym_tools)
+ out_file.write(json.dumps(row) + "\n")
+ num_written += 1
+ return num_written
+
+
+def prepare() -> Path:
+ """Download and convert the EnterpriseOps-Gym public split. Returns the output path."""
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
+
+ local_tasks_root = os.getenv(LOCAL_TASKS_ENV_VAR)
+ total = 0
+ with open(OUTPUT_FPATH, "w") as out_file:
+ try:
+ for domain in DOMAINS:
+ tasks = load_tasks_from_hf(HF_REPO_ID, MODE, domain)
+ count = _convert_domain(domain, tasks, out_file)
+ print(f"{domain}: {count} tasks (HuggingFace)")
+ total += count
+ except Exception as e:
+ if not local_tasks_root:
+ raise RuntimeError(
+ f"Could not download {HF_REPO_ID} from HuggingFace ({type(e).__name__}: {e}). "
+ f"If this machine has no Hub egress, fetch the dataset elsewhere or set "
+ f"{LOCAL_TASKS_ENV_VAR}= (e.g. .../data/revised) to "
+ f"convert local task JSONs instead."
+ ) from e
+ print(f"HuggingFace unreachable ({type(e).__name__}); falling back to local tasks at {local_tasks_root}")
+ out_file.seek(0)
+ out_file.truncate()
+ total = 0
+ for domain_dir in sorted(Path(local_tasks_root).iterdir()):
+ if not domain_dir.is_dir() or domain_dir.name not in DOMAIN_SNAPSHOTS:
+ continue
+ tasks = load_tasks_from_dir(domain_dir)
+ count = _convert_domain(domain_dir.name, tasks, out_file)
+ print(f"{domain_dir.name}: {count} tasks (local fallback)")
+ total += count
+
+ print(f"Wrote {total} tasks to {OUTPUT_FPATH}")
+ return OUTPUT_FPATH
+
+
+if __name__ == "__main__":
+ prepare()
diff --git a/resources_servers/enterpriseops_gym/PARITY.md b/resources_servers/enterpriseops_gym/PARITY.md
new file mode 100644
index 0000000000..af59cbf80d
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/PARITY.md
@@ -0,0 +1,125 @@
+# Parity Evidence: NeMo Gym Port vs Native EnterpriseOps-Gym
+
+This document consolidates the evidence that this resources server + `simple_agent` /
+`turn_logging_agent` reproduce the upstream [EnterpriseOps-Gym](https://github.com/ServiceNow/EnterpriseOps-Gym)
+harness's scoring behavior. All live comparisons: `azure/openai/gpt-4.1-mini` via an
+OpenAI-compatible gateway, temperature 0.0, max 16384 output tokens, concurrency 8,
+oracle mode, the same live MCP containers and seed databases for both harnesses.
+
+## 1. Static parity (unit level)
+
+- `verifier_engine.py` is a line-for-line port of upstream `benchmark/verifier.py` +
+ the scoring semantics of `benchmark/executor.py`, pinned by **golden fixtures generated
+ by running the original implementation** on shared inputs
+ (`tests/generate_parity_golden.py`, 19 extraction + 14 comparison cases, byte-identical).
+- Intentionally preserved upstream quirks (do not "fix" without breaking leaderboard
+ comparability):
+ - **Verifier name-collapse**: results are keyed by verifier name; duplicate-named
+ verifiers overwrite so only the last per name is scored (upstream `executor.py:474`).
+ An earlier same-named failure can be masked. `strict_verifiers: true` switches the
+ reward to every-verifier-counts for RL.
+ - Verifiers with unknown `gym_name` are skipped entirely (not counted).
+ - Loose comparison semantics (`0 != "0"`; type errors -> failed comparison).
+ - Tool observations are `json.dumps()`, matching what the upstream
+ harness feeds its model; tool merge order is per task's `gym_servers_config` order.
+- Tool schemas advertised to the model pass through the upstream schema cleaner
+ (nullable-type collapse, required-list demotion), bound non-strict.
+- The public oracle split contains **only `database_state` verifiers** (3,496/3,496), so
+ LLM-judge (`response_check`) semantics do not affect any number below; the judge
+ temperature is pinned to 0.0 regardless for full-split parity.
+
+## 2. Live task-level parity (12 CSM tasks, Phase 2)
+
+Same 12 tasks through both harnesses: **12/12 identical success/fail outcomes, 12/12
+identical collapsed-verifier counts and name sets**.
+
+## 3. Full public split, single runs (649 tasks)
+
+| Run | Harness / agent | Macro success % |
+|---|---|---|
+| A | port / simple_agent | 16.4 |
+| B | native EOG | 16.8 |
+| C | port / turn_logging_agent | 17.8 |
+
+- Per-task agreement: A↔B 90.4% (McNemar exact p = 0.90), C↔A 93.7% (p = 0.21),
+ C↔B 89.9% (p = 0.46). Disagreements symmetric in every pairing.
+- Collapsed-verifier scoring structure identical on 100% of cleanly completed tasks in
+ every pairing.
+- Stratified paired bootstrap (10k): every pairwise macro delta CI spans zero
+ (e.g. B−A [−2.2, +3.0] pp). **Single-run macro deltas under ~3 pp are unreadable** on
+ this benchmark/model/gateway.
+- Turn-0 prompts across harnesses differ by a constant −2 tokens (−0.04%): prompt
+ serialization is byte-equivalent and ruled out as a divergence driver.
+
+## 4. Definitive variance experiment (k=5 per implementation, 6,480 rollouts)
+
+Design: 5 interleaved blocks with alternating implementation order; full container-fleet
+restart before every pass (fd-leak reset); 645-task panel present in all 10 passes.
+
+| Metric | Result |
+|---|---|
+| mean@5 macro | port **16.54 ± 0.73** vs native **16.76 ± 0.99** → Δ −0.23 pp |
+| Per-task preference | **67 tasks favor port, 67 favor native**, 511 tied (sign p = 1.0) |
+| Outcome flip rate, within-implementation | 6.57% (port), 6.05% (native) |
+| Outcome flip rate, between implementations | 9.80% → excess **+3.49 pp, permutation p < 0.002** |
+| First-tool-call divergence | 2.4–2.6% within, 8.60% between (byte-equal prompts) |
+| Sensitivity (passes 1–4 only) | Δ −0.31 pp (unchanged) |
+
+**Conclusion.** The implementations are **score-equivalent to within ±0.7 pp with no
+directional bias**. A statistically robust but direction-free effect exists between the
+two API serving paths (Responses API vs Chat Completions at the gateway): it flips ~3.5%
+more borderline task outcomes than a same-implementation rerun, rooted at the very first
+sampled action, and moves no aggregate or per-task scores. It is a property of the
+inference gateway, not of either harness. Eliminating it requires deterministic
+self-hosted serving (vLLM, greedy + fixed seed).
+
+**Calibration guidance.** ~6.3% of task outcomes flip on *any* rerun at temperature 0
+through a hosted gateway; ~20% of tasks are flaky. Report mean@k (k≥5 → ±0.7 pp) rather
+than single-run scores.
+
+## 5. Cross-stack validation (k=5 on dedicated vLLM serving)
+
+The performance sweep ([PERF.md](PERF.md)) doubles as an independent k=5 replication on a
+different stack: Nemotron 3 Nano FP8 (reasoning enabled, ~13k output tokens/task) on
+4×H100 vLLM, with **both harnesses on the identical chat-completions endpoint** — a
+designed falsification test of §4's serving-path attribution. Panel: 641 tasks present in
+all 10 passes. Success is flat across concurrency in both harnesses (Cochran's Q 5.40 /
+4.32, df=4, n.s.), licensing the five levels as quasi-repeats (within-pairs span
+concurrency levels, which affects both harnesses identically).
+
+| Metric | Gateway (§4) | vLLM, same endpoint |
+|---|---:|---:|
+| Within-harness flip rate | ~6.3% | 14.7% |
+| Between-harness flip rate | 9.80% | 16.24% |
+| Harness excess | +3.49 pp (p<0.002) | **+1.57 pp** (p<0.0025) |
+| Excess relative to noise floor | 55% | **11%** |
+
+**The §4 attribution survives its falsification test**: removing the API serving-path
+confound collapsed the cross-harness trajectory effect from 55% to 11% of the noise floor
+(3.49 → 1.57 pp absolute, despite a 2.3× noisier base). The small residual is real and
+remains direction-free: mean Δp̂ +0.62 pp, **112 tasks favor the port vs 106 native**
+(sign p = 0.735), per-level McNemar all p ≥ 0.14 with alternating discordance direction,
+task-difficulty correlation r = 0.811.
+
+**Formal equivalence (TOST)**: macro 24.94% (port) vs 24.35% (native); Δ 90% CI
+[−0.82, +1.97] pp lies within a ±2 pp margin → **statistically equivalent within ±2 pp at
+α = 0.05**.
+
+**New calibration for reasoning models**: on this stack only 59% of tasks are
+deterministic-and-agreeing across all 10 runs (vs 78% on the gateway) and 41% are flaky
+(vs 20%) — ~30× more sampled tokens per task gives batch-numerics divergence ~30× more
+opportunities to flip a trajectory. Single-run scores for reasoning models on this
+benchmark are correspondingly noisier; report mean@5.
+
+## 6. Operational findings (upstream-relevant)
+
+- Most EOG MCP containers leak ~5 file descriptors per task lifecycle; at the default
+ ulimit (1024) a container serves ~200 tasks before seeding fails with
+ "unable to open database file". Restart containers between large runs (or use
+ `gym_url_pools` replicas).
+- The upstream runner (`utils/task_queue_worker.py`) never retrieves task results, so
+ task exceptions are silently dropped (~2 tasks/pass observed); its executor also leaves
+ orphaned database files when seeding fails mid-retry.
+- `ng_collect_rollouts` aborts the batch on a terminal `/run` error; reruns with
+ `+resume_from_cache=true` complete exactly the missing tasks. A continue-on-error
+ collection mode would remove the manual resume step.
diff --git a/resources_servers/enterpriseops_gym/PERF.md b/resources_servers/enterpriseops_gym/PERF.md
new file mode 100644
index 0000000000..f40fbabeb5
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/PERF.md
@@ -0,0 +1,74 @@
+# Performance: NeMo Gym Port vs Native EnterpriseOps-Gym at Scale
+
+Companion to [PARITY.md](PARITY.md) (score equivalence). This document reports the
+high-concurrency throughput comparison on dedicated GPU serving.
+
+## Setup
+
+- **Box**: 4× H100-80GB (TP=4), 124 vCPU, 720 GB RAM (Brev/Hyperstack)
+- **Model**: `nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-FP8` on vLLM (`--max-model-len 131072`,
+ reasoning enabled; ~13k output tokens/task), served locally — both harnesses hit the
+ identical `/v1/chat/completions` endpoint (port via the `vllm_model` server), removing
+ the API-serving-path confound identified in the parity work
+- **Workload**: full oracle public split (649 tasks, 8 domains incl. hybrid), temperature 0,
+ max 16384 output tokens, identical task order
+- **Protocol**: sequential passes; full MCP-container-fleet + vLLM restart before every
+ pass (fd-leak reset, no prefix-cache carryover); one pass per (harness, concurrency)
+- **Agents**: port = `simple_agent`; native = ReAct orchestrator (its equivalent loop)
+
+## Results
+
+
+
+| c | Port wall | Native wall | Native/Port | Port tasks/min | Native tasks/min |
+|---:|---:|---:|---:|---:|---:|
+| 8 | 2h 44m | 4h 40m | **1.71×** | 3.97 | 2.31 |
+| 16 | 2h 04m | 3h 12m | **1.54×** | 5.22 | 3.37 |
+| 32 | 1h 42m | 2h 17m | **1.34×** | 6.33 | 4.72 |
+| 64 | 1h 30m | 1h 52m | **1.25×** | 7.24 | 5.79 |
+| 128 | 1h 27m | 1h 39m | **1.14×** | 7.46 | 6.53 |
+
+All 10 passes completed: port 649/649 tasks at every level with zero retries; native 647
+at every level (2 tasks/pass silently dropped by its runner — known upstream bug).
+Success rates were 22–25% for both harnesses at every level (within single-run noise of
+each other per the k=5 calibration in PARITY.md): the throughput gap costs no accuracy.
+
+## Interpretation
+
+1. **At matched concurrency the port is 1.14–1.71× faster**, with the largest gap at the
+ low concurrency levels closest to the native harness's documented defaults (4–5).
+2. **Concurrency-equivalence: native needs roughly 4× the client concurrency** to match
+ the port — native's best (c=128) lands between the port's c=32 and c=64 results.
+3. **Hardware efficiency: the port saturates the box at c=64** (within 3% of the c=128
+ throughput floor); **native never reaches the floor** in the tested range (still +14%
+ at c=128). On this hardware the native harness cannot extract full machine throughput.
+4. **Cost framing**: one full-split eval = 1h 27m (port, c≥64) vs 4h 40m (native, c=8) of
+ 4×H100 time — a 3.2× GPU-hour difference at deployed-as-documented settings.
+
+## Mechanism
+
+GPU utilization read 97–99% with ~75 GB KV in use for *every* pass, while client CPU
+peaked at 18 of 124 cores — yet wall-clocks differ by up to 71% on identical silicon.
+`nvidia-smi` utilization measures kernel-busy time, not batch occupancy: the native
+harness's per-request connection setup, per-task MCP handshake + tool re-discovery, and
+sequential verifier execution insert dead time between agent turns, shrinking vLLM's
+continuous batch. The port's pooled connections, persistent MCP sessions, and concurrent
+verifiers keep the queue fed. (Queue-depth sampling was not captured in this run; the
+mechanism is inferred from the GPU-busy + wall-gap + CPU-idle triad.)
+
+The trend direction is the signature: as client concurrency rises, both harnesses
+asymptote toward the same GPU-bound floor and the ratio narrows (1.71× → 1.14×) —
+client-side overhead is amortized by parallelism but never fully hidden.
+
+## Caveats
+
+- One pass per (harness, level); per the k=5 variance study, single-run success rates
+ carry ±1.5–3pp noise — but the wall-clock ratio is monotone across all five levels,
+ which no plausible noise process produces.
+- The c=16 level ran ~1 day after the others (session loss; each level is self-contained
+ behind fleet+vLLM restarts) and lands exactly on the trend curve.
+- Native's 2 dropped tasks/pass mean it performed ~0.3% less work — negligible, and in
+ native's favor.
+
+Raw artifacts: `timings.csv`, per-pass rollout JSONLs / result dirs, GPU/CPU sampler CSVs
+(retained offline; see the benchmark kit's `analyze_results.py`).
diff --git a/resources_servers/enterpriseops_gym/README.md b/resources_servers/enterpriseops_gym/README.md
new file mode 100644
index 0000000000..e99c0374f0
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/README.md
@@ -0,0 +1,76 @@
+# EnterpriseOps-Gym Resources Server
+
+Adapts the [ServiceNow EnterpriseOps-Gym](https://github.com/ServiceNow/EnterpriseOps-Gym)
+benchmark (Apache 2.0) to NeMo Gym: 1,150 stateful enterprise tool-use tasks across 8 domains
+(Calendar, CSM, Drive, Email, HR, ITSM, Teams, Hybrid), executed against the upstream
+Dockerized MCP gym servers and graded by SQL verifiers on final database state.
+
+## Architecture
+
+- The upstream MCP gym servers stay external (Docker containers, one per domain). This server
+ is a thin adapter: per-rollout `/seed_session` seeds a fresh database from the task's SQL
+ snapshot and pins `{gym -> database_id}` to the session cookie; a catch-all `POST /{tool_name}`
+ proxies tool calls with the session's `x-database-id` and task context headers; `/verify`
+ runs the task's verifiers (ported verbatim from EOG) and deletes the databases.
+- `mcp_client.py` — pooled-aiohttp port of EOG's MCP/JSON-RPC client (one MCP session per gym
+ server; per-call database ids; in-memory seed SQL cache).
+- `verifier_engine.py` — line-for-line port of EOG's verifier engine (`database_state`,
+ `response_check` LLM judge, `tool_execution`), including its **name-collapse scoring quirk**:
+ duplicate-named verifiers overwrite each other and only the last one per name is scored.
+ The headline `reward` preserves that for leaderboard parity; strict every-verifier metrics
+ (`strict_success`, `strict_pass_rate`) are emitted alongside for RL reward shaping
+ (`strict_verifiers: true` switches the reward to strict).
+- `convert_tasks.py` / `snapshot_tools.py` — convert EOG task JSONs (local or the
+ `ServiceNow-AI/EnterpriseOps-Gym` HF dataset) into NeMo Gym JSONL rows, baking in tool
+ schemas from per-domain `tools/list` snapshots.
+
+## Prerequisites
+
+1. The EnterpriseOps-Gym checkout with `gym_dbs.zip` unzipped (`seed_sql_root` config points at it).
+2. The upstream MCP gym Docker containers running (default ports: csm 8001, teams 8002,
+ calendar 8003, email 8004, itsm 8006, hr 8008, drive 8009).
+
+## Usage
+
+```bash
+# Snapshot tool schemas from a running gym server (one-time, per domain)
+python resources_servers/enterpriseops_gym/snapshot_tools.py \
+ --gym-url http://localhost:8001 --gym-name sn-csm-server \
+ --output resources_servers/enterpriseops_gym/data/tools/csm.json
+
+# Convert EOG task JSONs to a NeMo Gym dataset
+python resources_servers/enterpriseops_gym/convert_tasks.py \
+ --tasks-dir ../enterpriseops-gym/data/revised/csm \
+ --tools-snapshot resources_servers/enterpriseops_gym/data/tools/csm.json \
+ --domain csm --mode oracle \
+ --output resources_servers/enterpriseops_gym/data/csm_revised.jsonl
+
+# Run servers + collect rollouts
+ng_run "+config_paths=[resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml,responses_api_models/openai_model/configs/openai_model.yaml]"
+ng_collect_rollouts +agent_name=enterpriseops_gym_simple_agent \
+ +input_jsonl_fpath=resources_servers/enterpriseops_gym/data/csm_revised.jsonl \
+ +output_jsonl_fpath=results/enterpriseops_csm.jsonl
+```
+
+## Parity notes
+
+Ported bug-for-bug from EOG (do not "fix" here; see `verifier_engine.py` docstring):
+SQL result extraction/comparison semantics, the verifier name-collapse, skipping verifiers
+with unknown `gym_name`, judge prompts, and the model-observation encoding of tool results.
+EOG judges `response_check` with the policy model itself; `judge_model_server` defaults to
+`policy_model` to match.
+
+## Licensing and data provenance
+
+- **Upstream benchmark**: [EnterpriseOps-Gym](https://github.com/ServiceNow/EnterpriseOps-Gym)
+ (ServiceNow) is licensed **Apache 2.0**; `verifier_engine.py` ports its scoring semantics
+ and the parity fixtures were generated by running the original engine.
+- **Task data**: the full benchmark dataset is the public HuggingFace dataset
+ [`ServiceNow-AI/EnterpriseOps-Gym`](https://huggingface.co/datasets/ServiceNow-AI/EnterpriseOps-Gym),
+ downloaded at `benchmarks/enterpriseops/prepare.py` time and never committed. Committed
+ data is limited to: 13 sample tasks derived from the EOG repository's task files,
+ `data/example.jsonl` (5 CSM sample tasks), one hand-authored synthetic hybrid task used
+ by tests (`data/hybrid_synthetic.jsonl`, written with LLM assistance against live
+ container schemas), and tool-schema snapshots (`data/tools/*.json`) captured from the
+ public EOG Docker containers.
+- **This integration**: Apache 2.0, same as NeMo Gym.
diff --git a/resources_servers/enterpriseops_gym/RLPILOT.md b/resources_servers/enterpriseops_gym/RLPILOT.md
new file mode 100644
index 0000000000..dbf0a8894b
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/RLPILOT.md
@@ -0,0 +1,186 @@
+# RL Rollout-Collection Pilot: GRPO Readiness with Zero Code Changes
+
+Companion to [PARITY.md](PARITY.md) (score equivalence) and [PERF.md](PERF.md)
+(throughput at scale). This document reports the pilot that validates the existing
+integration as an RL rollout collector — token-ID capture, reward signal, and
+group-variance (trainability) measurement — using **configuration only**: no code
+changes to the resources server, agent, or model server.
+
+## Setup
+
+Same stack as [PERF.md](PERF.md): `nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-FP8` on
+vLLM (4× H100, TP=4, reasoning enabled), live MCP container fleet, oracle public
+split. Rollouts collected with the stock `ng_collect_rollouts` +
+`enterpriseops_gym_simple_agent`.
+
+The one non-default switch RL needs:
+
+```
+++policy_model.responses_api_models.vllm_model.return_token_id_information=true
+```
+
+With it, every sampled assistant message carries `generation_token_ids`,
+`generation_log_probs`, and `prompt_token_ids` (plus `routed_experts` for this MoE
+model) — the `_ForTraining` payload NeMo RL consumes. Without it, rollouts are
+silently token-free: **verify the resolved config** (`curl
+localhost:11000/global_config_dict_yaml | grep return_token_id_information`) before
+any collection run intended for training.
+
+## Design and runs
+
+k rollouts per task; a task group is *mixed* when its rollouts disagree — mixed
+groups are where GRPO's group-relative advantage is nonzero, so the fraction of
+mixed groups is the trainability signal.
+
+| Run | Tasks | k | Sampling | Success | Binary-mixed groups |
+|---|---|---:|---|---:|---:|
+| v1 | first 20 rows | 4 | temp 1.0 | 0/80 | — (token IDs absent) |
+| v2 | first 20 rows | 4 | temp 0.6, top_p 0.95 | 1/80 | — (subset artifact, below) |
+| t0 control | first 20 rows | 1 | temp 0.0 | 1/20 | — |
+| **v3** | **20 mixed-band tasks** | **8** | **temp 0.6, top_p 0.95** | **89/160 (55.6%)** | **15/20** |
+
+All runs: `max_output_tokens: 16384`, concurrency 32 (v3: 160 rollouts in 22 min —
+consistent with the PERF.md throughput at this concurrency).
+
+## The task-subset trap (the pilot's main methodological lesson)
+
+v1/v2 initially read as "sampling destroys performance" (0–1% success vs the
+22–25% full-split baseline). Every intermediate hypothesis — reasoning runaway,
+truncation, token-ID-flag side effects, fd-leaked fleet — was eliminated by
+inspection; the control run then failed at **temperature 0 too**, and scoring the
+PERF.md sweep's own five temp-0 passes on the same 20 tasks gave 0–1/20 (mean
+strict pass rate 0.41–0.50, identical to the pilot's 0.45–0.51).
+
+The cause: `+limit=N` takes the **first N rows of the benchmark file, which is not
+shuffled** — the head of the file is a single-domain block of tasks that define
+3–12 verifiers each and are nearly unwinnable under all-or-nothing scoring (agents
+passed ~50% of verifiers on them in every run, at every temperature). Nothing was
+broken and sampling cost nothing; the subset was unrepresentative.
+
+**Rule: never pilot or smoke-test with `+limit` on this benchmark.** Select tasks
+deliberately (below), or shuffle first.
+
+## Curriculum selection from repeat-run data
+
+The PERF.md sweep doubles as k=5 temp-0 outcome data per task. Of the 645-task
+panel, **190 tasks (29%) are in the mixed band** (1–4 successes out of 5) — the
+natural GRPO curriculum, since tasks that flip on rerun are exactly the tasks
+where sampled groups will mix. v3 used the 20 tasks closest to 50% (2–3 wins/5).
+
+Selection mechanics: rollout rows join to benchmark rows via `_ng_task_index`
+(the row's position in the input file). Content-based keys do **not** survive the
+collector's input materialization — hash-matching rollouts to raw benchmark rows
+silently matches zero rows.
+
+## v3 results — the go/no-go numbers
+
+| Metric | Result | Reading |
+|---|---|---|
+| Token-ID coverage | 156/156 assistant messages | training data flows end-to-end |
+| Success | 89/160 = 55.6% | dead-center of the sweep-predicted 40–60% band → temp 0.6 sampling costs nothing |
+| Binary-mixed groups | **15/20** | nonzero GRPO advantage on 75% of curriculum tasks at k=8 |
+| Strict-mixed groups | 17/20 | fractional reward (`strict_pass_rate`) has gradient almost everywhere |
+| Mean within-group binary std | **0.341** | strong advantage signal (0/1-reward maximum is 0.5) |
+
+## Recommended GRPO configuration
+
+- **Curriculum**: tasks with repeat-run success in the ~20–80% band (190/645 on
+ this model; recompute per policy model from a k≥5 temp-0 sweep). Refresh as the
+ policy improves — the band moves.
+- **Reward**: binary `reward` (leaderboard-comparable) as the objective;
+ `strict_pass_rate` (per-verifier fraction, name-collapse disabled — see
+ PARITY.md §1) as shaping or fallback where binary groups are unmixed.
+- **Sampling**: temperature 0.6, top_p 0.95 (Nemotron reasoning recommendation),
+ `max_output_tokens` 16384. Temp 1.0 measured strictly worse on this model.
+- **Group size**: k=8 gave 75% mixed groups on a 40–60%-band curriculum.
+- **Eval**: mean@k, never single runs — this stack's reasoning models flip ~15% of
+ task outcomes on any rerun (PARITY.md §5).
+
+## Operational notes for long collection runs
+
+- **Restart the MCP fleet every ~200 task lifecycles** (fd leak, PARITY.md §6);
+ a training loop's rollout phase hits this budget quickly.
+- **Point `RAY_TMPDIR` at a large scratch mount.** With the default `/tmp`, each
+ `ng_run` leaves a Ray session directory behind; orphaned `raylet`/`gcs_server`
+ processes also outlive `pkill -f ng_run` and pin deleted files until killed.
+ A filled root disk here fails with Python's "No usable temporary directory".
+- **Watch syslog growth** on vLLM hosts (~GB/day observed); vacuum journals and
+ truncate before multi-day runs.
+
+## Phase 4 addendum: deployment shape for GRPO training (measured sizing)
+
+Sizing for full-parameter GRPO of Nemotron 3 Nano 30B-A3B against this
+environment, via the documented NeMo Gym → NeMo RL path. Three budgets decide
+the shape.
+
+**Trainer memory.** Optimizer state is per-parameter, not per-active-parameter:
+BF16 weights 60 GB + BF16 grads 60 GB + fp32 Adam ~360 GB ≈ **480 GB static**,
+sharded across the node, before activations and the colocated vLLM engine.
+
+**Train-sequence length (measured).** GRPO trains on the full concatenated
+trajectory. Exact final-turn sequence lengths (`len(prompt_token_ids) +
+len(generation_token_ids)` from the v3 rollouts): min 10.2k / median 20.2k /
+p90 36.0k / max 65.7k. Extended to the full 192-task mixed band via a
+calibrated chars-per-token estimate (4.00), taking each task's **longest**
+trajectory over the sweep's 5 passes (conservative):
+
+| Sequence cap | Mixed-band tasks kept |
+|---:|---:|
+| 16k | 23/192 (12%) |
+| 24k | 67/192 (35%) |
+| 32k | 121/192 (63%) |
+| 48k | 171/192 (89%) |
+| **64k** | **181/192 (94%)** |
+
+The band's median worst-case (28.8k) sits right at the 32k boundary, so an
+80 GB-class cap makes much of the curriculum flicker in and out; a ~200k tail
+(max 213k) is not worth keeping at any cap.
+
+**Rollout wall-clock.** The workload is environment-bound multi-turn generation:
+measured 160 rollouts / 22 min at c=32 on 4×H100 FP8; training generation runs
+the live policy in BF16 (≈½ the per-GPU throughput). A step of 32 prompts × k=8
+= 256 rollouts ≈ 25 min generation on 8 GPUs (serve DP=2 × TP=4 — two engine
+replicas beat TP=8 at this request mix) + 5–10 min training → **~30–35 min/step,
+~45 steps/day colocated**.
+
+**Shape ranking** (proof-point strength, descending):
+
+1. **8× B300 (288 GB), single node, colocated** — 2.3 TB total vs 480 GB
+ static: memory ceases to be a design constraint. Train at a 96–128k cap,
+ keeping the full 64k curriculum plus part of the long tail (11 tasks sit
+ between 64k and 213k), with generous KV headroom for higher generation
+ concurrency during the rollout phase. Same Blackwell day-0 smoke tests as
+ B200 below.
+2. **8× B200 (192 GB), single node, colocated** — 1.54 TB total vs 480 GB
+ static; train at a 64k cap and keep 94% of the curriculum; Blackwell BF16
+ throughput cuts step time to ~20 min. Day-0 smoke tests: Mamba-hybrid
+ training kernels on sm_100 in the NeMo RL container, and one full
+ train → weight-refit → generate cycle.
+3. **8× H200 (141 GB), single node, colocated** — comfortable at a 48k cap
+ (89% of curriculum).
+4. **2× 8× H100, disaggregated** (generation node + trainer node) — full 640 GB
+ for the trainer; per-step weight refit moves ~60 GB cross-node, so use
+ InfiniBand-class interconnect.
+5. **8× H100, single node** — fits at a 32k cap with aggressive activation
+ checkpointing, forfeiting ~37% of the mixed band; expect OOM-tuning time.
+6. **LoRA fallback (4–8× H100)** — optimizer state collapses; also the escape
+ hatch if full-FT of the hybrid Mamba/MoE arch hits framework issues.
+
+**Node layout.** Trainer sharded across all GPUs; vLLM generation DP=2×TP=4 BF16
+with sleep/wake colocation; head server + resources server + MCP fleet on the
+same node's CPUs (whole environment peaked at 18/124 cores in the PERF.md
+sweep). Run 2–3 MCP replicas per gym via `gym_url_pools` and script a fleet
+recreate every ~15–20 steps (fd budget, PARITY.md §6). Reward is pure SQL — no
+judge model, no extra GPU. 256 GB+ RAM; ~1 TB NVMe scratch (BF16 checkpoints are
+60 GB each); `RAY_TMPDIR` and HF cache on the big mount.
+
+**Proof-point run sketch** (~1 week): k=5 × 649 baseline eval (doubles as
+curriculum screening for the policy model) → train on ~⅔ of the in-cap mixed
+band, hold out ⅓ + full split → 100–200 GRPO steps, temp 0.6, strict fractional
+reward as training signal with held-out *binary* success as the honest metric →
+final mean@5 bookend. Pre-registered success: held-out band +≥10pp, full-split
+macro +≥2pp at mean@5 (resolvable: mean@5 noise is ±0.7 pp, PARITY.md §4–5).
+
+Raw artifacts: `results/rl_pilot/` on the collection host (`rollouts_v2.jsonl`,
+`rollouts_t0_control.jsonl`, `pilot_tasks_v3.jsonl`, `rollouts_v3.jsonl` +
+aggregate metrics).
diff --git a/resources_servers/enterpriseops_gym/app.py b/resources_servers/enterpriseops_gym/app.py
new file mode 100644
index 0000000000..27d98754be
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/app.py
@@ -0,0 +1,541 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""EnterpriseOps-Gym resources server.
+
+Adapts the ServiceNow EnterpriseOps-Gym benchmark (external MCP gym servers + SQL/judge
+verifiers) to NeMo Gym:
+
+- ``/seed_session`` seeds a fresh database per rollout on each task gym server (SQL content
+ cached in memory, seeding bounded by a per-gym semaphore) and pins {gym -> database_id}
+ to the NeMo Gym session cookie.
+- A catch-all ``POST /{tool_name}`` route proxies tool calls to the right MCP gym server
+ with the session's ``x-database-id`` and task context headers. The response body is the
+ MCP JSON-RPC ``result`` object, byte-compatible with what the EOG harness feeds its model.
+- ``/verify`` runs the task's verifiers via the ported EOG verifier engine. The headline
+ ``reward`` uses EOG's name-collapsed all-pass semantics for leaderboard parity; strict
+ every-verifier metrics are also emitted for RL reward shaping. Verify is idempotent
+ (results are cached per session) and always deletes the rollout's databases.
+- A TTL janitor deletes databases of sessions that never reached verify (killed rollouts).
+"""
+
+import asyncio
+import json
+import logging
+import time
+from pathlib import Path
+from typing import Any, Dict, List, Optional, Tuple
+
+from fastapi import FastAPI, Request, Response
+from pydantic import BaseModel, ConfigDict, Field
+
+from nemo_gym import PARENT_DIR
+from nemo_gym.base_resources_server import (
+ BaseResourcesServerConfig,
+ BaseSeedSessionRequest,
+ BaseSeedSessionResponse,
+ BaseVerifyRequest,
+ BaseVerifyResponse,
+ SimpleResourcesServer,
+)
+from nemo_gym.config_types import ModelServerRef
+from nemo_gym.openai_utils import NeMoGymResponse
+from nemo_gym.server_utils import SESSION_ID_KEY, get_response_json, raise_for_status
+from resources_servers.enterpriseops_gym.mcp_client import MCPGymClient, load_seed_sql
+from resources_servers.enterpriseops_gym.verifier_engine import VerifierEngine
+
+
+logger = logging.getLogger(__name__)
+
+
+RESERVED_ROUTES = {"seed_session", "verify", "aggregate_metrics"}
+
+
+class EnterpriseOpsGymResourcesServerConfig(BaseResourcesServerConfig):
+ # Maps EOG gym server names (e.g. "sn-csm-server") to base URLs, overriding the
+ # mcp_server_url baked into the dataset rows. Useful for pointing at replicas or
+ # non-default hosts without re-converting the dataset.
+ gym_url_overrides: Dict[str, str] = Field(default_factory=dict)
+
+ # Replica pools: gym server name -> list of base URLs. Each seed_session pins its
+ # rollout to one replica round-robin (all tool calls / SQL / delete stay on it).
+ # This is the horizontal-scale lever for RL rollout collection — run N copies of a
+ # domain's MCP container and list them here. Takes precedence over gym_url_overrides.
+ gym_url_pools: Dict[str, List[str]] = Field(default_factory=dict)
+
+ # Root directory for resolving relative seed_database_file paths from the dataset
+ # (EOG task paths look like "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_x.sql").
+ seed_sql_root: str = "../enterpriseops-gym"
+
+ # Database seeding executes a full SQL dump on the gym server; bound concurrent seeds
+ # per gym server so large rollout batches don't stampede it.
+ max_concurrent_seeds: int = 4
+
+ # Sessions that never reach /verify (killed rollouts) get their databases deleted by
+ # the janitor after this TTL. Verified sessions are dropped after the TTL as well.
+ session_ttl_seconds: float = 3600.0
+ janitor_interval_seconds: float = 300.0
+
+ # False (default) = EOG leaderboard parity: reward is all-pass over NAME-COLLAPSED
+ # verifier results (duplicate-named verifiers overwrite; see verifier_engine.py).
+ # True = strict RL mode: reward is all-pass over every defined verifier.
+ strict_verifiers: bool = False
+
+ tool_call_timeout_seconds: float = 30.0
+ sql_timeout_seconds: float = 30.0
+
+ # Judge model for response_check verifiers. EOG uses the policy model as its own judge;
+ # point this at policy_model for parity, or pin a fixed judge for RL.
+ judge_model_server: Optional[ModelServerRef] = None
+ # Extra responses-create params merged into judge calls (e.g. temperature, max_output_tokens).
+ judge_responses_create_params: Dict[str, Any] = Field(default_factory=dict)
+
+
+class SessionGym(BaseModel):
+ gym_name: str
+ base_url: str
+ mcp_endpoint: str = "/mcp"
+ database_id: Optional[str] = None
+ context: Dict[str, Any] = Field(default_factory=dict)
+ auth_config: Optional[Dict[str, Any]] = None
+
+
+class SessionState(BaseModel):
+ gyms: Dict[str, SessionGym] = Field(default_factory=dict)
+ tool_to_gym: Dict[str, str] = Field(default_factory=dict)
+ created_at: float
+ dbs_deleted: bool = False
+ verify_result: Optional[Dict[str, Any]] = None
+ # Per-tool-call latency records, in execution order: {tool, gym, latency_ms}.
+ tool_latencies: List[Dict[str, Any]] = Field(default_factory=list)
+
+
+class EnterpriseOpsSeedSessionRequest(BaseSeedSessionRequest):
+ model_config = ConfigDict(extra="allow")
+ verifier_metadata: Dict[str, Any]
+
+
+class EnterpriseOpsSeedSessionResponse(BaseSeedSessionResponse):
+ databases: Dict[str, Optional[str]] = Field(default_factory=dict)
+
+
+class EnterpriseOpsVerifyRequest(BaseVerifyRequest):
+ model_config = ConfigDict(extra="allow")
+ verifier_metadata: Dict[str, Any]
+
+
+class EnterpriseOpsVerifyResponse(BaseVerifyResponse):
+ model_config = ConfigDict(extra="allow")
+
+ # EOG-parity scoring (name-collapsed verifier results; see verifier_engine.py).
+ overall_success: bool
+ verifier_pass_rate: float
+ verification_results: Dict[str, Any]
+
+ # Strict scoring over every defined verifier (RL reward shaping).
+ strict_success: bool
+ strict_pass_rate: float
+
+ num_verifiers_defined: int
+ num_verifiers_scored: int
+ num_tool_calls: int
+
+ # Per-tool-call latencies in execution order (this server proxies every MCP call,
+ # so it can time them — something the upstream harness cannot).
+ tool_latencies_ms: List[Dict[str, Any]] = Field(default_factory=list)
+
+
+class EnterpriseOpsGymResourcesServer(SimpleResourcesServer):
+ model_config = ConfigDict(arbitrary_types_allowed=True)
+
+ config: EnterpriseOpsGymResourcesServerConfig
+ sessions: Dict[str, SessionState] = Field(default_factory=dict)
+
+ gym_clients: Dict[str, MCPGymClient] = None
+ seed_semaphores: Dict[str, asyncio.Semaphore] = None
+ replica_counters: Dict[str, int] = None
+ janitor_task: Optional[asyncio.Task] = None
+
+ def model_post_init(self, __context: Any) -> None:
+ self.gym_clients = {}
+ self.seed_semaphores = {}
+ self.replica_counters = {}
+
+ def setup_webserver(self) -> FastAPI:
+ app = super().setup_webserver()
+
+ # Catch-all tool proxy. Registered after the base routes, so /seed_session,
+ # /verify, and /aggregate_metrics keep precedence (Starlette matches in order).
+ app.post("/{tool_name}")(self.call_tool)
+
+ return app
+
+ # ------------------------------------------------------------------
+ # Gym client / session helpers
+ # ------------------------------------------------------------------
+
+ def _get_gym_client(self, gym: SessionGym) -> MCPGymClient:
+ key = json.dumps([gym.base_url, gym.mcp_endpoint, gym.auth_config], sort_keys=True)
+ client = self.gym_clients.get(key)
+ if client is None:
+ client = MCPGymClient(
+ base_url=gym.base_url,
+ auth_config=gym.auth_config,
+ mcp_endpoint=gym.mcp_endpoint,
+ tool_call_timeout_seconds=self.config.tool_call_timeout_seconds,
+ sql_timeout_seconds=self.config.sql_timeout_seconds,
+ )
+ self.gym_clients[key] = client
+ return client
+
+ def _get_seed_semaphore(self, base_url: str) -> asyncio.Semaphore:
+ semaphore = self.seed_semaphores.get(base_url)
+ if semaphore is None:
+ semaphore = asyncio.Semaphore(self.config.max_concurrent_seeds)
+ self.seed_semaphores[base_url] = semaphore
+ return semaphore
+
+ def _resolve_seed_sql_path(self, seed_database_file: str) -> Optional[Path]:
+ if not seed_database_file:
+ return None
+ path = Path(seed_database_file)
+ if path.is_absolute():
+ return path
+ # ng_run forks servers with CWD = the server dir, but users naturally write
+ # seed_sql_root relative to the gym repo root — try both.
+ candidates = [
+ Path(self.config.seed_sql_root) / path,
+ PARENT_DIR / self.config.seed_sql_root / path,
+ ]
+ for candidate in candidates:
+ if candidate.exists():
+ return candidate
+ return candidates[0]
+
+ def _parse_session_gyms(self, verifier_metadata: Dict[str, Any]) -> Dict[str, SessionGym]:
+ gym_servers_config = verifier_metadata.get("gym_servers_config") or []
+ if not gym_servers_config:
+ raise ValueError("verifier_metadata.gym_servers_config is missing or empty")
+
+ gyms: Dict[str, SessionGym] = {}
+ for idx, server_config in enumerate(gym_servers_config):
+ for field in ("mcp_server_name", "mcp_server_url"):
+ if field not in server_config:
+ raise ValueError(f"gym_servers_config[{idx}] missing required field: '{field}'")
+
+ gym_name = server_config["mcp_server_name"]
+ pool = self.config.gym_url_pools.get(gym_name)
+ if pool:
+ # Pin this rollout to one replica, round-robin across sessions.
+ replica_index = self.replica_counters.get(gym_name, 0)
+ self.replica_counters[gym_name] = replica_index + 1
+ base_url = pool[replica_index % len(pool)]
+ else:
+ base_url = self.config.gym_url_overrides.get(gym_name, server_config["mcp_server_url"])
+ gyms[gym_name] = SessionGym(
+ gym_name=gym_name,
+ base_url=base_url,
+ mcp_endpoint=server_config.get("mcp_endpoint", "/mcp"),
+ context=server_config.get("context") or {},
+ auth_config=server_config.get("auth_config"),
+ )
+ return gyms
+
+ async def _seed_gym_database(self, gym: SessionGym, seed_database_file: str) -> None:
+ """Seed one gym's database. Mirrors EOG: a missing seed file logs an error and
+ proceeds with database_id=None instead of failing the rollout."""
+ seed_path = self._resolve_seed_sql_path(seed_database_file)
+ if seed_path is None or not seed_path.exists():
+ logger.error(f"SQL seed file not found for gym '{gym.gym_name}': {seed_path}")
+ return
+
+ sql_content = load_seed_sql(str(seed_path))
+ client = self._get_gym_client(gym)
+ gym.database_id = await client.seed_database(
+ sql_content, seed_semaphore=self._get_seed_semaphore(gym.base_url)
+ )
+
+ async def _delete_session_dbs(self, state: SessionState) -> None:
+ if state.dbs_deleted:
+ return
+ state.dbs_deleted = True
+ for gym in state.gyms.values():
+ if gym.database_id:
+ try:
+ await self._get_gym_client(gym).delete_database(gym.database_id)
+ except Exception as e:
+ logger.error(f"Failed to delete database {gym.database_id} for gym '{gym.gym_name}': {e}")
+
+ # ------------------------------------------------------------------
+ # Janitor
+ # ------------------------------------------------------------------
+
+ def _ensure_janitor(self) -> None:
+ # janitor_interval_seconds <= 0 disables the background janitor (tests call
+ # cleanup_expired_sessions directly).
+ if self.config.janitor_interval_seconds <= 0:
+ return
+ if self.janitor_task is None or self.janitor_task.done():
+ self.janitor_task = asyncio.create_task(self._janitor_loop())
+
+ async def _janitor_loop(self) -> None: # pragma: no cover
+ while True:
+ await asyncio.sleep(self.config.janitor_interval_seconds)
+ try:
+ await self.cleanup_expired_sessions()
+ except Exception as e:
+ logger.error(f"Janitor sweep failed: {e}")
+
+ async def cleanup_expired_sessions(self, now: Optional[float] = None) -> int:
+ """Delete databases and drop state for sessions older than the TTL. Returns count."""
+ now = now if now is not None else time.time()
+ expired = [
+ session_id
+ for session_id, state in self.sessions.items()
+ if now - state.created_at > self.config.session_ttl_seconds
+ ]
+ for session_id in expired:
+ state = self.sessions.pop(session_id)
+ if not state.dbs_deleted:
+ logger.warning(f"Janitor deleting databases for expired session {session_id} (rollout never verified)")
+ await self._delete_session_dbs(state)
+ return len(expired)
+
+ # ------------------------------------------------------------------
+ # Routes
+ # ------------------------------------------------------------------
+
+ async def seed_session(
+ self, request: Request, body: EnterpriseOpsSeedSessionRequest
+ ) -> EnterpriseOpsSeedSessionResponse:
+ session_id = request.session[SESSION_ID_KEY]
+
+ gyms = self._parse_session_gyms(body.verifier_metadata)
+ gym_servers_config = body.verifier_metadata.get("gym_servers_config") or []
+
+ # Seed all gyms' databases concurrently (bounded by per-gym-server semaphores).
+ await asyncio.gather(
+ *(
+ self._seed_gym_database(
+ gyms[server_config["mcp_server_name"]], server_config.get("seed_database_file", "")
+ )
+ for server_config in gym_servers_config
+ )
+ )
+
+ state = SessionState(
+ gyms=gyms,
+ tool_to_gym=body.verifier_metadata.get("tool_to_gym") or {},
+ created_at=time.time(),
+ )
+ self.sessions[session_id] = state
+ self._ensure_janitor()
+
+ return EnterpriseOpsSeedSessionResponse(databases={name: gym.database_id for name, gym in gyms.items()})
+
+ async def call_tool(self, tool_name: str, request: Request) -> Response:
+ """Catch-all MCP tool proxy.
+
+ The response body is exactly ``json.dumps()`` (or ``{}`` on transport
+ error) — the same observation string the EOG harness feeds its model.
+ """
+ if tool_name in RESERVED_ROUTES: # pragma: no cover - starlette routes these first
+ return Response(content=json.dumps({}), media_type="application/json", status_code=404)
+
+ session_id = request.session[SESSION_ID_KEY]
+ state = self.sessions.get(session_id)
+ if state is None:
+ return Response(
+ content=json.dumps({"error": "No seeded session found. Call /seed_session first."}),
+ media_type="application/json",
+ status_code=400,
+ )
+
+ try:
+ arguments = json.loads((await request.body()) or b"{}")
+ except json.JSONDecodeError as e:
+ return Response(
+ content=json.dumps({"error": f"Invalid JSON tool arguments: {e}"}),
+ media_type="application/json",
+ status_code=400,
+ )
+
+ # Route the tool to its gym: dataset-provided mapping, else the only gym.
+ gym_name = state.tool_to_gym.get(tool_name)
+ if gym_name is None and len(state.gyms) == 1:
+ gym_name = next(iter(state.gyms))
+ gym = state.gyms.get(gym_name)
+ if gym is None:
+ return Response(
+ content=json.dumps({"error": f"Tool '{tool_name}' is not mapped to any gym server"}),
+ media_type="application/json",
+ status_code=400,
+ )
+
+ client = self._get_gym_client(gym)
+ tool_t0 = time.monotonic()
+ tool_result = await client.call_tool(tool_name, arguments, database_id=gym.database_id, context=gym.context)
+ state.tool_latencies.append(
+ {
+ "tool": tool_name,
+ "gym": gym.gym_name,
+ "latency_ms": round((time.monotonic() - tool_t0) * 1000, 1),
+ }
+ )
+
+ # EOG parity: the model observes json.dumps(tool_result.get("result", {})).
+ return Response(content=json.dumps(tool_result.get("result", {})), media_type="application/json")
+
+ async def _judge(self, system_prompt: str, user_prompt: str) -> str:
+ """response_check judge call. EOG judges with a plain system+user chat completion."""
+ judge_body = {
+ "input": [
+ {"role": "system", "content": system_prompt},
+ {"role": "user", "content": user_prompt},
+ ],
+ } | dict(self.config.judge_responses_create_params)
+
+ response = await self.server_client.post(
+ server_name=self.config.judge_model_server.name,
+ url_path="/v1/responses",
+ json=judge_body,
+ )
+ await raise_for_status(response)
+ judge_response = NeMoGymResponse.model_validate(await get_response_json(response))
+
+ texts = [
+ content.text
+ for item in judge_response.output
+ if item.type == "message"
+ for content in item.content
+ if content.type == "output_text"
+ ]
+ return "".join(texts)
+
+ @staticmethod
+ def build_model_response(response: NeMoGymResponse) -> Tuple[Dict[str, Any], int]:
+ """Build the EOG-shape model_response dict from a Responses API trajectory.
+
+ EOG passes {"content": , "tool_calls": [{"name", "args"}, ...]} to its
+ verifiers, where the final response is the last AI text (or, when the loop ended on a
+ tool step, the last tool observation).
+ """
+ final_response = ""
+ tool_calls: List[Dict[str, Any]] = []
+ for item in response.output:
+ item_type = getattr(item, "type", None)
+ if item_type == "message" and getattr(item, "role", None) == "assistant":
+ final_response = "".join(
+ content.text for content in item.content if getattr(content, "type", None) == "output_text"
+ )
+ elif item_type == "function_call":
+ try:
+ args = json.loads(item.arguments)
+ except (json.JSONDecodeError, TypeError):
+ args = item.arguments
+ tool_calls.append({"name": item.name, "args": args})
+ elif item_type == "function_call_output":
+ final_response = item.output
+
+ return {"content": final_response, "tool_calls": tool_calls}, len(tool_calls)
+
+ async def verify(self, request: Request, body: EnterpriseOpsVerifyRequest) -> EnterpriseOpsVerifyResponse:
+ session_id = request.session[SESSION_ID_KEY]
+ state = self.sessions.get(session_id)
+ if state is None:
+ raise ValueError("No seeded session found for verify. Call /seed_session first.")
+
+ # Idempotency: the harness may retry verify if the response was lost; the databases
+ # are gone after the first verify, so replay the cached result instead of re-running.
+ if state.verify_result is not None:
+ return EnterpriseOpsVerifyResponse.model_validate(state.verify_result)
+
+ try:
+ verifiers = body.verifier_metadata.get("verifiers") or []
+ model_response, num_tool_calls = self.build_model_response(body.response)
+
+ engine = VerifierEngine(
+ gym_clients={name: self._get_gym_client(gym) for name, gym in state.gyms.items()},
+ judge_fn=self._judge if self.config.judge_model_server else None,
+ )
+ verification_results, all_verifier_results = await engine.run_verifiers(
+ verifiers=verifiers,
+ model_response=model_response,
+ gym_databases={name: gym.database_id for name, gym in state.gyms.items()},
+ gym_contexts={name: gym.context for name, gym in state.gyms.items()},
+ )
+ finally:
+ await self._delete_session_dbs(state)
+
+ # EOG-parity scoring over the name-collapsed results (executor.py semantics).
+ # NOTE: like upstream, an empty result set (all verifiers skipped for unknown gyms)
+ # yields all([]) == True here — preserved for leaderboard comparability (PARITY.md §1);
+ # `num_verifiers_scored` exposes the condition to callers.
+ total_verifiers = len(verification_results)
+ passed_verifiers = sum(1 for v in verification_results.values() if v.get("passed", False))
+ overall_success = all(v["passed"] for v in verification_results.values())
+ verifier_pass_rate = passed_verifiers / total_verifiers if total_verifiers > 0 else 0.0
+
+ # Strict scoring over every defined verifier (skipped verifiers count as failed).
+ # Unlike the parity path above, strict mode feeds RL rewards, so an empty verifier
+ # set must NOT score as success.
+ strict_passed = [entry["result"].get("passed", False) for entry in all_verifier_results]
+ strict_success = bool(strict_passed) and all(strict_passed)
+ strict_pass_rate = sum(strict_passed) / len(strict_passed) if strict_passed else 0.0
+
+ reward = float(strict_success) if self.config.strict_verifiers else float(overall_success)
+
+ verify_response = EnterpriseOpsVerifyResponse(
+ **body.model_dump(),
+ reward=reward,
+ overall_success=overall_success,
+ verifier_pass_rate=verifier_pass_rate,
+ verification_results=verification_results,
+ strict_success=strict_success,
+ strict_pass_rate=strict_pass_rate,
+ num_verifiers_defined=len(verifiers),
+ num_verifiers_scored=total_verifiers,
+ num_tool_calls=num_tool_calls,
+ tool_latencies_ms=state.tool_latencies,
+ )
+ state.verify_result = verify_response.model_dump()
+ return verify_response
+
+ def compute_metrics(self, tasks: List[List[Dict[str, Any]]]) -> Dict[str, Any]:
+ """Per-domain breakdown mirroring the EOG leaderboard (per-domain success + macro avg)."""
+ domain_rewards: Dict[str, List[float]] = {}
+ domain_pass_rates: Dict[str, List[float]] = {}
+ domain_strict: Dict[str, List[float]] = {}
+ for task_group in tasks:
+ for rollout in task_group:
+ domain = (rollout.get("verifier_metadata") or {}).get("domain") or "unknown"
+ domain_rewards.setdefault(domain, []).append(rollout.get("reward", 0.0))
+ domain_pass_rates.setdefault(domain, []).append(rollout.get("verifier_pass_rate", 0.0))
+ domain_strict.setdefault(domain, []).append(rollout.get("strict_pass_rate", 0.0))
+
+ metrics: Dict[str, Any] = {}
+ for domain, rewards in sorted(domain_rewards.items()):
+ metrics[f"{domain}/success_rate"] = sum(rewards) / len(rewards)
+ metrics[f"{domain}/verifier_pass_rate"] = sum(domain_pass_rates[domain]) / len(domain_pass_rates[domain])
+ metrics[f"{domain}/strict_pass_rate"] = sum(domain_strict[domain]) / len(domain_strict[domain])
+ metrics[f"{domain}/num_rollouts"] = len(rewards)
+
+ per_domain_success = [metrics[f"{d}/success_rate"] for d in domain_rewards]
+ if per_domain_success:
+ metrics["macro_success_rate"] = sum(per_domain_success) / len(per_domain_success)
+ return metrics
+
+
+if __name__ == "__main__":
+ EnterpriseOpsGymResourcesServer.run_webserver()
diff --git a/resources_servers/enterpriseops_gym/assets/throughput_chart.png b/resources_servers/enterpriseops_gym/assets/throughput_chart.png
new file mode 100644
index 0000000000..766eeacd6a
Binary files /dev/null and b/resources_servers/enterpriseops_gym/assets/throughput_chart.png differ
diff --git a/resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml b/resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml
new file mode 100644
index 0000000000..39194fd23d
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml
@@ -0,0 +1,54 @@
+enterpriseops_gym:
+ resources_servers:
+ enterpriseops_gym:
+ entrypoint: app.py
+ domain: agent
+ verified: false
+ description: EnterpriseOps-Gym enterprise tool-use benchmark (external MCP gym servers + SQL/judge verifiers)
+ value: Improve stateful multi-step enterprise planning and tool use
+
+ # Root for resolving relative seed_database_file paths from dataset rows
+ # (the unzipped gym_dbs.zip lives in the EnterpriseOps-Gym checkout).
+ seed_sql_root: ../enterpriseops-gym
+
+ # Optional gym_name -> base_url overrides (else the mcp_server_url baked into
+ # each dataset row is used, e.g. http://localhost:8001 for sn-csm-server).
+ gym_url_overrides: {}
+
+ max_concurrent_seeds: 4
+ session_ttl_seconds: 3600
+ janitor_interval_seconds: 300
+
+ # false = EOG leaderboard parity reward (name-collapsed verifiers, all must pass).
+ # true = strict RL reward (every defined verifier must pass).
+ strict_verifiers: false
+
+ tool_call_timeout_seconds: 30
+ sql_timeout_seconds: 30
+
+ # EOG judges response_check verifiers with the policy model itself; keep that
+ # default for parity. Pin a fixed judge model here for RL runs.
+ judge_model_server:
+ type: responses_api_models
+ name: policy_model
+ # Parity pin: EOG's judge runs on the policy client's temperature (0.0 in eval
+ # configs); without this, judge calls fall through to the provider default (1.0).
+ judge_responses_create_params:
+ temperature: 0.0
+
+enterpriseops_gym_simple_agent:
+ responses_api_agents:
+ simple_agent:
+ entrypoint: app.py
+ # EOG's ReAct orchestrator runs up to 50 reason-act iterations.
+ max_steps: 50
+ resources_server:
+ type: resources_servers
+ name: enterpriseops_gym
+ model_server:
+ type: responses_api_models
+ name: policy_model
+ datasets:
+ - name: example
+ type: example
+ jsonl_fpath: resources_servers/enterpriseops_gym/data/example.jsonl
diff --git a/resources_servers/enterpriseops_gym/configs/enterpriseops_gym_turnlog.yaml b/resources_servers/enterpriseops_gym/configs/enterpriseops_gym_turnlog.yaml
new file mode 100644
index 0000000000..8c97c27319
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/configs/enterpriseops_gym_turnlog.yaml
@@ -0,0 +1,34 @@
+# EnterpriseOps-Gym with the per-turn-telemetry agent (eval-team logging schema).
+# Adds a turn_logging_agent alongside the standard stack; collect with
+# ng_collect_rollouts +agent_name=enterpriseops_gym_turn_logging_agent ...
+# then export via export_eval_telemetry.py.
+# The metadata block below re-states the inherited server's metadata so the
+# README environment-table generator (scripts/update_env_list.py) can render
+# this config's row; it merges as a no-op over the base config.
+enterpriseops_gym:
+ resources_servers:
+ enterpriseops_gym:
+ domain: agent
+ verified: false
+ description: EnterpriseOps-Gym benchmark with per-turn telemetry logging (timings, token usage incl. cache hits, tool latencies)
+ value: Improve stateful multi-step enterprise planning and tool use
+
+config_paths:
+ - resources_servers/enterpriseops_gym/configs/enterpriseops_gym.yaml
+
+enterpriseops_gym_turn_logging_agent:
+ responses_api_agents:
+ turn_logging_agent:
+ entrypoint: app.py
+ # EOG parity: same max_steps as the standard agent.
+ max_steps: 50
+ resources_server:
+ type: resources_servers
+ name: enterpriseops_gym
+ model_server:
+ type: responses_api_models
+ name: policy_model
+ datasets:
+ - name: example
+ type: example
+ jsonl_fpath: resources_servers/enterpriseops_gym/data/example.jsonl
diff --git a/resources_servers/enterpriseops_gym/convert_tasks.py b/resources_servers/enterpriseops_gym/convert_tasks.py
new file mode 100644
index 0000000000..b050e0915e
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/convert_tasks.py
@@ -0,0 +1,243 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Convert EnterpriseOps-Gym task JSONs into NeMo Gym dataset JSONL rows.
+
+Sources: a local folder of EOG task configs (e.g. data/revised/csm in the EOG checkout) or
+the ServiceNow-AI/EnterpriseOps-Gym HuggingFace dataset (config=mode, split=domain).
+
+Tool schemas are baked in from per-domain tools/list snapshots (see snapshot_tools.py),
+filtered by each task's selected_tools (empty = all tools, as upstream) minus
+restricted_tools, preserving snapshot (server) order and cleaning schemas with the EOG
+schema cleaner — matching the tool set the upstream harness would advertise to the model.
+
+Output row shape:
+ {
+ "responses_create_params": {"input": [system, user], "tools": [...]},
+ "verifier_metadata": {task_id, domain, mode, gym_servers_config, verifiers,
+ selected_tools, restricted_tools, tool_to_gym}
+ }
+"""
+
+import argparse
+import json
+import logging
+from pathlib import Path
+from typing import Any, Dict, List, Optional, Tuple
+
+from resources_servers.enterpriseops_gym.schema_utils import clean_json_schema
+
+
+logger = logging.getLogger(__name__)
+
+# Fields the HF dataset stores as JSON strings (mirrors evaluate.py).
+HF_JSON_STRING_FIELDS = {"gym_servers_config", "verifiers"}
+
+
+def strip_private_keys(task: Dict[str, Any]) -> Dict[str, Any]:
+ """Mirror EOG's load_config: drop top-level and per-verifier keys starting with '_'."""
+ task = {k: v for k, v in task.items() if not k.startswith("_")}
+ if task.get("verifiers"):
+ task["verifiers"] = [
+ {k: v for k, v in verifier.items() if not k.startswith("_")} for verifier in task["verifiers"]
+ ]
+ return task
+
+
+def load_snapshots(snapshot_paths: List[Path]) -> Dict[str, List[Dict[str, Any]]]:
+ """Load tool snapshots. Returns {gym_name: [raw tool dicts]} — merging happens PER TASK
+ (see build_tools_for_task) because EOG discovers tools from each task's own gyms in the
+ task's gym_servers_config order, and duplicate tool names resolve first-wins in that order.
+ """
+ gym_tools: Dict[str, List[Dict[str, Any]]] = {}
+ for snapshot_path in snapshot_paths:
+ with open(snapshot_path) as f:
+ snapshot = json.load(f)
+ gym_tools[snapshot["gym_name"]] = snapshot["tools"]
+ return gym_tools
+
+
+def build_tools_for_task(
+ task: Dict[str, Any], gym_tools: Dict[str, List[Dict[str, Any]]]
+) -> Tuple[List[Dict[str, Any]], Dict[str, str]]:
+ """Merge + filter + convert snapshot tools for one task, mirroring the upstream executor:
+ tools are discovered from the TASK's gyms in gym_servers_config order (duplicate names
+ keep the first occurrence, as executor._discover_and_merge_tools warns and does), then
+ the selected_tools filter applies (empty = all tools, discovery order), then
+ restricted_tools exclusion. Schemas go through the EOG cleaner. Output is Responses API
+ tool format.
+ """
+ selected = task.get("selected_tools") or []
+ restricted = set(task.get("restricted_tools") or [])
+
+ # Per-task merge over the task's own gyms, in the task's order (EOG parity).
+ merged_tools: List[Dict[str, Any]] = []
+ tool_to_gym: Dict[str, str] = {}
+ for server_config in task.get("gym_servers_config") or []:
+ gym_name = server_config.get("mcp_server_name")
+ if gym_name not in gym_tools:
+ logger.warning(f"No tools snapshot provided for gym '{gym_name}'; its tools will be missing.")
+ continue
+ for tool in gym_tools[gym_name]:
+ tool_name = tool.get("name", "unknown")
+ if tool_name in tool_to_gym:
+ logger.debug(
+ f"Tool '{tool_name}' duplicated across gyms "
+ f"('{tool_to_gym[tool_name]}' and '{gym_name}'); keeping first occurrence."
+ )
+ continue
+ merged_tools.append(tool)
+ tool_to_gym[tool_name] = gym_name
+
+ filtered = [t for t in merged_tools if not selected or t.get("name") in selected]
+ if selected:
+ missing = set(selected) - {t.get("name") for t in filtered}
+ if missing:
+ logger.warning(f"Task selected_tools not found in snapshots: {sorted(missing)}")
+ filtered = [t for t in filtered if t.get("name") not in restricted]
+
+ tools = [
+ {
+ "type": "function",
+ "name": tool["name"],
+ "description": tool.get("description", ""),
+ "parameters": clean_json_schema(
+ tool.get("inputSchema", {"type": "object", "properties": {}, "required": []})
+ ),
+ # EOG's LangChain path binds tools non-strict; strict mode would also reject
+ # the EOG-cleaned schemas (optional params, no additionalProperties: false).
+ "strict": False,
+ }
+ for tool in filtered
+ ]
+ task_tool_to_gym = {t["name"]: tool_to_gym[t["name"]] for t in tools}
+ return tools, task_tool_to_gym
+
+
+def convert_task(
+ task: Dict[str, Any],
+ task_id: str,
+ domain: str,
+ mode: str,
+ gym_tools: Dict[str, List[Dict[str, Any]]],
+) -> Dict[str, Any]:
+ task = strip_private_keys(task)
+
+ for required_field in ("system_prompt", "user_prompt"):
+ if required_field not in task:
+ raise ValueError(f"Task {task_id} missing required field: {required_field}")
+ if not task.get("gym_servers_config"):
+ raise ValueError(f"Task {task_id} missing gym_servers_config (legacy single-gym tasks are not supported)")
+
+ tools, task_tool_to_gym = build_tools_for_task(task, gym_tools)
+
+ return {
+ "responses_create_params": {
+ "input": [
+ {"role": "system", "content": task["system_prompt"]},
+ {"role": "user", "content": task["user_prompt"]},
+ ],
+ "tools": tools,
+ },
+ "verifier_metadata": {
+ "task_id": task_id,
+ "domain": domain,
+ "mode": mode,
+ "gym_servers_config": task["gym_servers_config"],
+ "verifiers": task.get("verifiers") or [],
+ "selected_tools": task.get("selected_tools") or [],
+ "restricted_tools": task.get("restricted_tools") or [],
+ "tool_to_gym": task_tool_to_gym,
+ },
+ }
+
+
+def load_tasks_from_dir(tasks_dir: Path) -> List[Tuple[str, Dict[str, Any]]]:
+ tasks = []
+ for task_path in sorted(tasks_dir.glob("*.json")):
+ with open(task_path) as f:
+ tasks.append((task_path.stem, json.load(f)))
+ return tasks
+
+
+def load_tasks_from_hf(hf_dataset: str, mode: str, domain: str) -> List[Tuple[str, Dict[str, Any]]]:
+ """Load tasks from the EOG HuggingFace dataset (config=mode, split=domain), as evaluate.py does."""
+ from datasets import load_dataset as hf_load_dataset
+
+ tasks = []
+ hf_ds = hf_load_dataset(hf_dataset, mode, split=domain)
+ for i, row in enumerate(hf_ds):
+ task_id = row.get("task_id", f"task_{i}")
+ task = {}
+ for k, v in row.items():
+ if k in ("task_id", "domain"):
+ continue
+ if k in HF_JSON_STRING_FIELDS and isinstance(v, str):
+ v = json.loads(v)
+ task[k] = v
+ tasks.append((task_id, task))
+ return tasks
+
+
+def convert(
+ tasks: List[Tuple[str, Dict[str, Any]]],
+ snapshot_paths: List[Path],
+ domain: str,
+ mode: str,
+ output: Path,
+ limit: Optional[int] = None,
+) -> int:
+ gym_tools = load_snapshots(snapshot_paths)
+
+ output.parent.mkdir(parents=True, exist_ok=True)
+ num_written = 0
+ with open(output, "w") as f:
+ for task_id, task in tasks[:limit]:
+ row = convert_task(task, task_id, domain, mode, gym_tools)
+ f.write(json.dumps(row) + "\n")
+ num_written += 1
+ return num_written
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(description=__doc__)
+ source = parser.add_mutually_exclusive_group(required=True)
+ source.add_argument("--tasks-dir", type=Path, help="Folder of EOG task JSON configs")
+ source.add_argument("--hf-dataset", help="HF dataset repo id (e.g. ServiceNow-AI/EnterpriseOps-Gym)")
+ parser.add_argument(
+ "--tools-snapshot",
+ type=Path,
+ action="append",
+ required=True,
+ help="Tools snapshot JSON from snapshot_tools.py (repeat for hybrid/multi-gym domains)",
+ )
+ parser.add_argument("--domain", required=True, help="EOG domain tag (e.g. csm); HF split when --hf-dataset")
+ parser.add_argument(
+ "--mode", default="oracle", help="EOG tool-set mode (e.g. oracle); HF config when --hf-dataset"
+ )
+ parser.add_argument("--output", required=True, type=Path)
+ parser.add_argument("--limit", type=int, default=None)
+ args = parser.parse_args()
+
+ if args.tasks_dir:
+ tasks = load_tasks_from_dir(args.tasks_dir)
+ else:
+ tasks = load_tasks_from_hf(args.hf_dataset, args.mode, args.domain)
+
+ num_written = convert(tasks, args.tools_snapshot, args.domain, args.mode, args.output, args.limit)
+ print(f"Wrote {num_written} rows to {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/resources_servers/enterpriseops_gym/data/csm_revised.jsonl b/resources_servers/enterpriseops_gym/data/csm_revised.jsonl
new file mode 100644
index 0000000000..20386a2749
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/csm_revised.jsonl
@@ -0,0 +1,12 @@
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Marc Henry needs to address a critical situation for Stark Industries. Update the existing entitlement for their Palo Alto Networks PA-3220 Variant 8 to our highest Enterprise support level, ensuring 24x7 coverage and removing any monthly case limits. Register a new critical case for this device, reporting that the Dataplane crashes repeatedly, using the phone channel. Assign the case to Curtis McCoy and the Escalation Management group. Ensure the mandatory Resolution SLA is applied to this case."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contact_by_portal_user", "description": "Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.", "parameters": {"type": "object", "properties": {"portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}}, "required": ["portal_user_id"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "update_entitlement", "description": "Update an entitlement (partial updates allowed). Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique ID of the entitlement to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "product_id": {"type": "integer", "description": "Update the product ID linked to the entitlement."}, "contract_id": {"type": "integer", "description": "Update the contract ID linked to the entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Update the support level."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Update the coverage hours."}, "max_cases_per_month": {"type": "integer", "description": "Update the maximum number of support cases per month."}, "active": {"type": "boolean", "description": "Set entitlement status as active (true) or inactive (false)."}}, "required": ["entitlement_id"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251205_153330_906_a8eea1c0_8c7a6205", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's coverage hours were updated to h24x7.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "expected_value": "h24x7", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's max case limit was set to unlimited (0).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT max_cases_per_month FROM entitlement WHERE entitlement_id = 73;", "expected_value": 0, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify that Entitlement 73's update timestamp is newer than its original data record to confirm the update occurred.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement WHERE entitlement_id = 73 AND sys_updated_on IS NOT NULL", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the new case (ID 1233) was created for the correct installed product (ID 42).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT installed_product_id FROM customer_case WHERE case_id = 1233;", "expected_value": 42, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the new case priority is 'critical' and channel is 'phone'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT priority FROM customer_case WHERE case_id = 1233 AND channel = 'phone';", "expected_value": "critical", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case (ID 1233) was correctly assigned to the Escalation Management group (ID 18).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT assignment_group_id FROM customer_case WHERE case_id = 1233;", "expected_value": 18, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case (ID 1233) was correctly assigned to Curtis McCoy (ID 177).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT assigned_to FROM customer_case WHERE case_id = 1233;", "expected_value": 177, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case initial state was correctly set to 'in_progress'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT state FROM customer_case WHERE case_id = 1233;", "expected_value": "in_progress", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify that the Critical Resolution SLA (ID 6) was linked to the new case (ID 1233).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify that the new case_sla entry's stage is set to 'in_progress'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT stage FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;", "expected_value": "in_progress", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's support level was updated to enterprise.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT support_level FROM entitlement WHERE entitlement_id = 73;", "expected_value": "enterprise", "comparison_type": "equals"}}], "selected_tools": ["find_user_group", "retrieve_installed_products", "update_case", "update_entitlement", "find_contact_by_portal_user", "find_sla_definitions", "find_entitlements", "find_user", "find_product", "link_new_case_sla", "create_new_case"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_contact_by_portal_user": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "update_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management assistant. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, ing record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account\u2019s data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) Default state = new. Verify the product or installed product belongs to the customer\u2019s account.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group. Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user\u2019s relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product\u2019s product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer\u2019s entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "During our December 5th, 2025 review of the London setup, we noticed that the facility with the older plot and curve address pattern in the 90s area is being reorganized. One of the P25-serial type devices at that location needs its records updated, and the device's warranty window is coming up soon.\nPlease update the system by relocating this device to the London site with the newer plot and street configuration, specifically the one on the Pratt Curve side, and ensure its status remains operational. After completing the update, please send a notification to the associated account contacts for this product so they're aware of the change."}], "tools": [{"type": "function", "name": "list_users", "description": "List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned.", "parameters": {"type": "object", "properties": {"email": {"type": "string", "description": "Filter by user email address (exact match) (unique)."}, "user_id": {"type": "integer", "description": "Filter by unique user identifier."}, "first_name": {"type": "string", "description": "Filter by user's first name."}, "last_name": {"type": "string", "description": "Filter by user's last name."}, "phone": {"type": "string", "description": "Filter by phone number."}, "role": {"type": "string", "enum": ["admin", "agent", "manager", "customer"], "description": "Filter by user role (admin, agent, manager, or customer)."}, "location_id": {"type": "integer", "description": "Filter by location identifier."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "created_after": {"type": "string", "description": "Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_locations", "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Unique identifier of the location."}, "name": {"type": "string", "description": "Name of the location."}, "active": {"type": "boolean", "description": "Whether the location is currently active."}, "plot_no": {"type": "string", "description": "Plot number of the location."}, "street": {"type": "string", "description": "Street address of the location."}, "city": {"type": "string", "description": "City where the location is situated."}, "country": {"type": "string", "description": "Country where the location is situated."}, "created_before": {"type": "string", "description": "Filter for locations created before this timestamp (ISO format)."}, "created_after": {"type": "string", "description": "Filter for locations created after this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "update_installed_product_details", "description": "Update an installed product (partial updates allowed). Combination of Account ID, Product ID, Serial Number should be unique.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID (required)."}, "location_id": {"type": "integer", "description": "Location/site ID where the product is installed."}, "account_id": {"type": "integer", "description": "Owning account ID for this installed product."}, "product_id": {"type": "integer", "description": "Product ID that was installed."}, "serial_number": {"type": "string", "description": "Unique serial number of the installed product.", "minLength": 1}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Status of the installed product."}, "warranty_end": {"type": "string", "description": "Warranty end date (YYYY-MM-DD)."}}, "required": ["installed_product_id"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "send_notification", "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Case ID this notification is related to."}, "knowledge_id": {"type": "integer", "description": "Optional knowledge article ID linked to this notification."}, "email": {"type": "string", "description": "Recipient email address of the notification.", "minLength": 1}, "type": {"type": "string", "enum": ["report", "update", "alert", "reminder", "solution_proposal", "next_steps", "other"], "description": "Type of notification being sent."}}, "required": ["case_id", "email", "type"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251205_154853_044_d4a463c3_fce76046", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "Verify Updated Installed Product", "description": "Verify Updated Installed Product", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) \nFROM installed_product AS ip\nWHERE ip.installed_product_id = 40\n AND ip.location_id = 692\n AND ip.status = 'in_use';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Create New Case", "description": "Verify Create New Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM customer_case AS c\nWHERE c.account_id = 8\n AND c.contact_id = 10\n AND c.channel = 'alert'\n AND c.priority = 'low'\n AND c.state = 'closed';\n ", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Notification Sent ", "description": "Verify Notification Sent ", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'marc.henry@stark-industries.com'\n AND n.type = 'update';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Notification Sent ", "description": "Verify Notification Sent ", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'tonya.stevens@stark-industries.com'\n AND n.type = 'update';\n", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["update_case", "send_notification", "create_new_case", "find_locations", "find_contacts", "update_installed_product_details", "list_users", "retrieve_installed_products"], "restricted_tools": [], "tool_to_gym": {"list_users": "sn-csm-server", "find_contacts": "sn-csm-server", "find_locations": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "update_installed_product_details": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "send_notification": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "The Wilson and Sons customer reached out via email, explaining that they had previously logged a case that was closed on 2nd October 2025 for their Managed Network Services asset but was eventually canceled. The issue is still ongoing, and they now want the case recreated and also mentioned that they want to escalate this since the problem has persisted for too long. Please open a case using the same contact, product, issue description, and priority from the canceled one, set the channel to email, assign it to the Case Assignment_2 team, and allocate it to agent Cory Vargas. Once the case is created, confirm that the entitlement is active and attach all SLAs appropriate for the priority level."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "check_user_membership", "description": "Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"user_id": {"type": "integer", "description": "User's unique id to check"}, "group_id": {"type": "integer", "description": "User group's unique id to check"}}, "required": ["user_id", "group_id"]}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "search_cases", "description": "Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case."}, "number": {"type": "string", "description": "Case number (unique human-readable reference)."}, "account_id": {"type": "integer", "description": "Filter by account ID. An account represents a business entity or organization."}, "contact_id": {"type": "integer", "description": "Filter by contact ID."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "installed_product_id": {"type": "integer", "description": "Filter by installed product ID. Unique identifier which relates to the installed product table record."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was communicated/created."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "State of the case."}, "short_description": {"type": "string", "description": "Short description of the case."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation."}, "reopen_count": {"type": "integer", "description": "Filter by number of times the case was reopened."}, "closed_on": {"type": "string", "description": "Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return cases created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251209_132736_542_99ba2325_6705caf4", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1765219280033_d7pqrz32b.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": {"user_id": 32, "name": "Jose Roberson", "email": "jose.roberson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verify case creation", "description": "Verify case creation", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM customer_case WHERE case_id = 1233 AND state = 'in_progress' AND assignment_group_id = 24 AND assigned_to = 427 AND channel = 'email' AND priority = 'critical' AND escalation_reason = 'customer_request' AND escalation = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify group membership", "description": "Verify group membership", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM user_group_member WHERE group_id = 24 AND user_id = 427;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify case sla 1", "description": "Verify case sla 1", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify case sla 2", "description": "Verify case sla 2", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 6;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_user_group", "update_case", "find_user", "find_entitlements", "find_contacts", "link_new_case_sla", "find_sla_definitions", "search_cases", "check_user_membership", "find_product", "find_account", "create_new_case"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "check_user_membership": "sn-csm-server", "find_contacts": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "search_cases": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Klein Black and Wood's India facility reported via community post that their Dell rack server keeps hitting kernel panics. I forgot to note the machine's serial, but I remember it wraps up with the digits 9300. Log this at mid-range priority through the community channel using their lead site contact. Pass it to the first foundation-level installed product support squad. Bind a response timer appropriate for that priority bracket. If possible, pick one that doesn't freeze during customer wait states. Get that timer ticking, but the case should show initial registration status, not active work if it's possible. The description must read 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' exactly as written."}], "tools": [{"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product_by_id", "description": "Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id.", "parameters": {"type": "object", "properties": {"product_id": {"type": "integer", "description": " Unique identifier of the product."}}, "required": ["product_id"]}, "strict": false}, {"type": "function", "name": "list_user_groups", "description": "List user groups with optional filters.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Filter by unique group identifier."}, "name": {"type": "string", "description": "Filter by group name (exact match, unique)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "type": {"type": "string", "enum": ["support", "backoffice", "field", "vendor"], "description": "Filter by group type (support, backoffice, field, vendor)."}, "created_after": {"type": "string", "description": "Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "get_accounts", "description": "List accounts with optional filters. All the inputs are optional, not providing any filter will return all accounts. Account represents a business entity or organization.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Filter by unique account identifier."}, "name": {"type": "string", "description": "Filter by account name (e.g., 'Acme Systems') (unique). Name of the company/organization associated with the account.", "minLength": 1}, "email_domain": {"type": "string", "description": "Filter by account email domain (e.g., 'acme.com'). it is the domain part of email addresses associated with the account or the website.", "minLength": 1}, "account_types": {"type": "array", "items": {"type": "string", "enum": ["customer", "partner", "internal"]}, "description": "Filter by one or more account types (customer, partner, internal)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "created_after": {"type": "string", "description": "Return only accounts created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only accounts created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_locations", "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Unique identifier of the location."}, "name": {"type": "string", "description": "Name of the location."}, "active": {"type": "boolean", "description": "Whether the location is currently active."}, "plot_no": {"type": "string", "description": "Plot number of the location."}, "street": {"type": "string", "description": "Street address of the location."}, "city": {"type": "string", "description": "City where the location is situated."}, "country": {"type": "string", "description": "Country where the location is situated."}, "created_before": {"type": "string", "description": "Filter for locations created before this timestamp (ISO format)."}, "created_after": {"type": "string", "description": "Filter for locations created after this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251210_002938_761_897c3e0b_f075229a", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "stephanie.todd@servicenow.com"}, "user_info": {"user_id": 6, "name": "Stephanie Todd", "email": "stephanie.todd@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Case created with correct attributes", "description": "Verify case was created with account_id=52, product_id=133, installed_product_id=295, priority=moderate, channel=community, exact description, and assignment_group_id=10", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND assignment_group_id = 10;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case linked to primary contact", "description": "Verify the case is associated with a primary contact (contact with is_primary=1) for account_id=52", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN contact c ON cc.contact_id = c.contact_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND c.is_primary = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case state updated to in_progress", "description": "Verify case state was changed to 'in_progress' (required by policy before SLA linking)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND state = 'in_progress' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Correct installed product linked (serial ends with 9300)", "description": "Verify the case is linked to installed_product_id=295 (Dell PowerEdge with serial ending in 9300 at Mumbai location)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case assigned to Installed Base Support group", "description": "Verify case was assigned to Installed Base Support (group_id=10) - the 'first foundation-level installed product support squad'", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Response SLA linked for moderate priority", "description": "Verify a response SLA for moderate priority was linked to the case (any moderate response SLA acceptable, since none with pause_on_pending=false exist)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id JOIN sla_definition sd ON cs.sla_def_id = sd.sla_def_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND sd.metric = 'response' AND sd.applies_to_priority = 'moderate' AND sd.active = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "SLA timer started (stage in_progress)", "description": "Verify the SLA was started with stage='in_progress' and start_time is set ('get that timer ticking')", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND cs.stage = 'in_progress' AND cs.start_time IS NOT NULL AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "No duplicate cases created", "description": "Verify exactly ONE case was created for this scenario (no duplicates)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case sys_updated_on changed after state transition", "description": "Verify case sys_updated_on timestamp is later than sys_created_on (confirms state was updated after creation)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND sys_updated_on > sys_created_on;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["link_new_case_sla", "create_new_case", "retrieve_installed_products", "get_accounts", "find_account", "list_user_groups", "update_case", "find_locations", "find_contacts", "find_product_by_id", "find_sla_definitions"], "restricted_tools": [], "tool_to_gym": {"find_account": "sn-csm-server", "find_product_by_id": "sn-csm-server", "list_user_groups": "sn-csm-server", "get_accounts": "sn-csm-server", "find_contacts": "sn-csm-server", "find_locations": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "As part of a readiness check for a new business-critical service and the broader rollout, a few coordinated updates are required. First, confirm that Curtis Mccoy is active and ready to take on high-impact responsibilities along with his team for this rollout. Then register a new active service named \u201cNetwork Resilience Health Check\u201d, and create an internal troubleshooting guide titled \u201cNetwork Resilience Health Check Troubleshooting\u201d for it.\n\nWithdraw the incorrectly opened case CS-0000888 for Stark, Petersen and Palmer so it no longer affects workload reporting. Next, create a phone-reported support case for the same account related to operational instability tied to this service. Validate entitlement coverage,route the case using the handling method currently in place for this implementation, link the troubleshooting guide as a suggested reference, apply the critical-response SLA, and ensure the case is positioned for immediate technical action with proper priority due to the high business risk involved."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "list_user_groups", "description": "List user groups with optional filters.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Filter by unique group identifier."}, "name": {"type": "string", "description": "Filter by group name (exact match, unique)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "type": {"type": "string", "enum": ["support", "backoffice", "field", "vendor"], "description": "Filter by group type (support, backoffice, field, vendor)."}, "created_after": {"type": "string", "description": "Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "list_group_members", "description": "List user group members with optional filters. Combination of group_id and user_id is unique.", "parameters": {"type": "object", "properties": {"member_id": {"type": "integer", "description": "Filter by unique membership identifier."}, "group_id": {"type": "integer", "description": "Filter by group identifier."}, "user_id": {"type": "integer", "description": "Filter by user identifier."}, "created_after": {"type": "string", "description": "Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "search_cases", "description": "Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case."}, "number": {"type": "string", "description": "Case number (unique human-readable reference)."}, "account_id": {"type": "integer", "description": "Filter by account ID. An account represents a business entity or organization."}, "contact_id": {"type": "integer", "description": "Filter by contact ID."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "installed_product_id": {"type": "integer", "description": "Filter by installed product ID. Unique identifier which relates to the installed product table record."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was communicated/created."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "State of the case."}, "short_description": {"type": "string", "description": "Short description of the case."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation."}, "reopen_count": {"type": "integer", "description": "Filter by number of times the case was reopened."}, "closed_on": {"type": "string", "description": "Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return cases created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "add_new_product", "description": "Create/register a product. Add product details. Products can be software, hardware, or services offered by the organization.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Name of the product (e.g., 'Premium Support Package') (unique).", "minLength": 1}, "category": {"type": "string", "enum": ["software", "hardware", "service"], "description": "Product category (software, hardware, or service)."}, "lifecycle_state": {"type": "string", "enum": ["active", "retired"], "description": "Lifecycle state of the product (active or retired)."}, "product_price": {"type": "integer", "description": "Price of the product in the smallest currency unit (e.g., cents)."}}, "required": ["name", "category", "lifecycle_state"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "create_knowledge", "description": "Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.", "parameters": {"type": "object", "properties": {"title": {"type": "string", "description": "Title of the knowledge article.", "minLength": 1}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Lifecycle state of the article."}, "body": {"type": "string", "description": "Body of the knowledge article."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Who can view the article: internal staff or external customers."}, "product_id": {"type": "integer", "description": "ID of the related product, if applicable."}, "owner_id": {"type": "integer", "description": "User ID of the article owner/author."}}, "required": ["title", "state", "body", "visibility", "owner_id"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251210_113549_827_d4a463c3_47b48a98", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "Verify New Product", "description": "Verify New Product", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS service_healthy_cnt\nFROM product AS p\nWHERE p.name = 'Network Resilience Health Check'\nAND p.category = 'service'\nAND p.lifecycle_state = 'active';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Update Case", "description": "Verify Update Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_888_canceled_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 888\nAND cc.state = 'canceled';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Knowledge Created", "description": "Verify Knowledge Created", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS kb_network_resilience_cnt\nFROM knowledge AS k\nWHERE k.title = 'Network Resilience Health Check Troubleshooting'\nAND k.state = 'published'\nAND k.visibility = 'internal'\nAND k.owner_id = 32\nAND k.product_id = 241;\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case", "description": "Verify New Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_network_resilience_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 1233 \nAND cc.account_id = 38\nAND cc.contact_id = 84\nAND cc.product_id = 241\nAND cc.channel = 'phone'\nAND cc.priority = 'critical'\nAND cc.state = 'in_progress'\nAND cc.assignment_group_id = 18\nAND cc.escalation = 1\nAND cc.escalation_reason = 'impact';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case Knowledge Link", "description": "Verify New Case Knowledge Link", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_1233_kb_370_cnt\nFROM case_knowledge AS ck\nWHERE ck.case_id = 1233\nAND ck.knowledge_id = 370\nAND ck.used_as = 'suggested';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case SLA", "description": "Verify New Case SLA", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_1234_sla_cnt\nFROM case_sla AS cs\nWHERE cs.case_id = 1233\nAND cs.sla_def_id = 1\nAND cs.stage = 'in_progress';\n", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_sla_definitions", "find_account", "link_new_case_sla", "find_entitlements", "search_cases", "list_group_members", "create_new_case", "find_contacts", "update_case", "create_knowledge", "list_user_groups", "link_case_knowledge", "find_user", "add_new_product"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "list_user_groups": "sn-csm-server", "list_group_members": "sn-csm-server", "find_contacts": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "search_cases": "sn-csm-server", "add_new_product": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "create_knowledge": "sn-csm-server", "link_case_knowledge": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "We have a critical outage due to repeated dataplane crashing on Stark Industries PA-3220, ending 8853 and urgent help needed as this issue is severely impacting operations. I suspect the issue stems from the prior support contract being inactive since it was supposed to be renewed back in May. I need immediate Escalation Management and top-tier 24x7 Enterprise support for this specific firewall. Please log a critical web case, contract with start date 18/11/2025, establish a new 12-month Enterprise support and link resolution SLA."}], "tools": [{"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product_by_id", "description": "Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id.", "parameters": {"type": "object", "properties": {"product_id": {"type": "integer", "description": " Unique identifier of the product."}}, "required": ["product_id"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "set_case_assignment_group", "description": "Set or change the assignment group for a case. Setting the assignment group helps route the case to the appropriate team for handling.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "assignment_group_id": {"type": "integer", "description": "Unique identifier of the assignment group to set."}}, "required": ["case_id", "assignment_group_id"]}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_knowledge", "description": "Retrieve knowledge articles with full-text search on title/body and structured filters. All inputs are optional; not providing any filter will return all knowledge articles. A knowledge article is a documented piece of information that provides solutions, answers, or guidance on specific topics to help users resolve issues or learn about products and services.", "parameters": {"type": "object", "properties": {"search_text": {"type": "string", "description": "Full-text search across article title and body. Free form search."}, "knowledge_id": {"type": "integer", "description": "Filter by unique knowledge article ID."}, "kb_number": {"type": "string", "description": "Filter by knowledge base number."}, "title": {"type": "string", "description": "Filter by article title."}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Filter by article lifecycle state."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Filter by article visibility. Internal for staff, external for customers/public."}, "product_id": {"type": "integer", "description": "Filter by related product ID."}, "owner_id": {"type": "integer", "description": "Filter by user ID of the article owner. User who authored the article."}, "created_before": {"type": "string", "description": "Retrieve articles created before this timestamp."}, "created_after": {"type": "string", "description": "Retrieve articles created after this timestamp."}, "limit": {"type": "integer", "description": "Limit the number of articles returned."}}}, "strict": false}, {"type": "function", "name": "enlist_new_contract", "description": "Create a new contract for an account. Contracts define the terms of service, support, or warranty agreements between the organization and its customers.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "ID of the account the contract is associated with."}, "contract_type": {"type": "string", "enum": ["support", "warranty", "subscription"], "description": "Type of contract to create."}, "contract_price": {"type": "integer", "description": "Price value for the contract."}, "status": {"type": "string", "enum": ["draft", "active", "suspended", "expired"], "description": "Initial status of the contract."}, "start_date": {"type": "string", "description": "Start date of the contract (YYYY-MM-DD)."}, "end_date": {"type": "string", "description": "End date of the contract (YYYY-MM-DD)."}}, "required": ["account_id", "contract_type", "status", "start_date", "end_date"]}, "strict": false}, {"type": "function", "name": "add_new_entitlement", "description": "Create a new entitlement. Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID to which the entitlement belongs."}, "product_id": {"type": "integer", "description": "Product ID associated with the entitlement (optional)."}, "contract_id": {"type": "integer", "description": "Contract ID linked to this entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level provided under the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours provided (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month."}, "active": {"type": "boolean", "description": "Indicates whether the entitlement is active (true) or inactive (false)."}}, "required": ["account_id", "support_level", "active"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251231_162628_797_a8eea1c0_0a53db6c", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": {"user_id": 4, "name": "Joanne Simpson", "email": "joanne.simpson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "enlist_new_contract", "description": "Verify the new active contract for Stark Industries has been created.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract WHERE account_id = 8 AND contract_type = 'support' AND status = 'active' AND contract_id = 154 AND end_date = '2026-11-18';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "enlist_new_contract", "description": "Verify the contract table was updated.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract WHERE contract_id = 154 AND sys_updated_on IS NOT NULL;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "add_new_entitlement", "description": "Verify the new Enterprise 24x7 entitlement for PA-3220 V8 exists.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement WHERE account_id = 8 AND product_id = 140 AND contract_id = 154 AND support_level = 'enterprise' AND coverage_hours = 'h24x7' AND active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "add_new_entitlement", "description": "Verify the contract record has been updated since entitlement creation.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract WHERE contract_id = 154 AND sys_updated_on > '2025-11-18';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the critical case was created and associated with the correct product/asset.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE case_id = 1233 AND account_id = 8 AND product_id = 140 AND installed_product_id = 42 AND priority = 'critical';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the contact's record was updated upon case creation.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contact WHERE contact_id = 10 AND sys_updated_on IS NOT NULL;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "set_case_assignment_group", "description": "Verify the critical case 1233 is assigned to Escalation Management.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE case_id = 1233 AND assignment_group_id = 18;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "set_case_assignment_group", "description": "Verify the Escalation Management group record timestamp was updated.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user_group WHERE group_id = 18 AND sys_updated_on IS NOT NULL;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_case", "description": "Verify case 1233 moved to 'in_progress' status.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE case_id = 1233 AND state = 'in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify the critical resolution SLA is linked to case 1233 and started.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6 AND stage = 'in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_case_knowledge", "description": "Verify the KB article 210 related to the PA-3220 V8 issue is linked to the case.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_knowledge WHERE case_id = 1233 AND knowledge_id = 210 AND used_as = 'suggested';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_case_knowledge", "description": "Verify case record was updated after linking knowledge.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE case_id = 1233 AND sys_updated_on IS NOT NULL;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_account", "enlist_new_contract", "create_new_case", "update_case", "find_product_by_id", "find_user_group", "set_case_assignment_group", "retrieve_knowledge", "find_sla_definitions", "link_case_knowledge", "add_new_entitlement", "find_contacts", "retrieve_installed_products", "link_new_case_sla", "find_entitlements"], "restricted_tools": [], "tool_to_gym": {"find_account": "sn-csm-server", "find_product_by_id": "sn-csm-server", "find_user_group": "sn-csm-server", "set_case_assignment_group": "sn-csm-server", "find_contacts": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "retrieve_knowledge": "sn-csm-server", "enlist_new_contract": "sn-csm-server", "add_new_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "link_case_knowledge": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "A critical failure has been reported at Stark Industries' new London Lab via phone, affecting their newly installed Juniper EX4300 Variant 7 with serial JEX-987654-NL. Do they hold 24x7 Enterprise support? If entitlement is missing or expired, procure and apply a 1-year contract extension and enterprise entitlement, effective 2025-11-27. Assign case to Tier 2 for immediate troubleshooting and send a solution proposal notification to Marc Henry."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "list_group_members", "description": "List user group members with optional filters. Combination of group_id and user_id is unique.", "parameters": {"type": "object", "properties": {"member_id": {"type": "integer", "description": "Filter by unique membership identifier."}, "group_id": {"type": "integer", "description": "Filter by group identifier."}, "user_id": {"type": "integer", "description": "Filter by user identifier."}, "created_after": {"type": "string", "description": "Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_knowledge", "description": "Retrieve knowledge articles with full-text search on title/body and structured filters. All inputs are optional; not providing any filter will return all knowledge articles. A knowledge article is a documented piece of information that provides solutions, answers, or guidance on specific topics to help users resolve issues or learn about products and services.", "parameters": {"type": "object", "properties": {"search_text": {"type": "string", "description": "Full-text search across article title and body. Free form search."}, "knowledge_id": {"type": "integer", "description": "Filter by unique knowledge article ID."}, "kb_number": {"type": "string", "description": "Filter by knowledge base number."}, "title": {"type": "string", "description": "Filter by article title."}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Filter by article lifecycle state."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Filter by article visibility. Internal for staff, external for customers/public."}, "product_id": {"type": "integer", "description": "Filter by related product ID."}, "owner_id": {"type": "integer", "description": "Filter by user ID of the article owner. User who authored the article."}, "created_before": {"type": "string", "description": "Retrieve articles created before this timestamp."}, "created_after": {"type": "string", "description": "Retrieve articles created after this timestamp."}, "limit": {"type": "integer", "description": "Limit the number of articles returned."}}}, "strict": false}, {"type": "function", "name": "add_location", "description": "Create a new location (site). A location represents a physical site or office associated with the organization, such as branch offices, warehouses, or service centers.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Name of the location/site (e.g., 'Downtown HQ').", "minLength": 1}, "active": {"type": "boolean", "description": "Whether the location is active (true) or inactive (false)."}, "plot_no": {"type": "string", "description": "Plot number of the location (optional)."}, "street": {"type": "string", "description": "Street address of the location (optional)."}, "city": {"type": "string", "enum": ["new_york", "london", "mumbai", "tokyo", "sydney"], "description": "City where the location is situated."}, "country": {"type": "string", "enum": ["usa", "uk", "india", "japan", "australia"], "description": "Country where the location is situated."}}, "required": ["name", "active", "city", "country"]}, "strict": false}, {"type": "function", "name": "register_new_installed_product", "description": "Register a new installed product at an account/location. Combination of Account ID, Product ID, Serial Number should be unique.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Location/site ID where the product is installed."}, "account_id": {"type": "integer", "description": "Owning account ID for this installed product."}, "product_id": {"type": "integer", "description": "Product ID that was installed."}, "serial_number": {"type": "string", "description": "Unique serial number of the installed product.", "minLength": 1}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Status of the installed product."}, "warranty_end": {"type": "string", "description": "Warranty end date (YYYY-MM-DD)."}}, "required": ["account_id", "product_id", "serial_number", "status"]}, "strict": false}, {"type": "function", "name": "enlist_new_contract", "description": "Create a new contract for an account. Contracts define the terms of service, support, or warranty agreements between the organization and its customers.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "ID of the account the contract is associated with."}, "contract_type": {"type": "string", "enum": ["support", "warranty", "subscription"], "description": "Type of contract to create."}, "contract_price": {"type": "integer", "description": "Price value for the contract."}, "status": {"type": "string", "enum": ["draft", "active", "suspended", "expired"], "description": "Initial status of the contract."}, "start_date": {"type": "string", "description": "Start date of the contract (YYYY-MM-DD)."}, "end_date": {"type": "string", "description": "End date of the contract (YYYY-MM-DD)."}}, "required": ["account_id", "contract_type", "status", "start_date", "end_date"]}, "strict": false}, {"type": "function", "name": "add_new_entitlement", "description": "Create a new entitlement. Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID to which the entitlement belongs."}, "product_id": {"type": "integer", "description": "Product ID associated with the entitlement (optional)."}, "contract_id": {"type": "integer", "description": "Contract ID linked to this entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level provided under the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours provided (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month."}, "active": {"type": "boolean", "description": "Indicates whether the entitlement is active (true) or inactive (false)."}}, "required": ["account_id", "support_level", "active"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}, {"type": "function", "name": "send_notification", "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Case ID this notification is related to."}, "knowledge_id": {"type": "integer", "description": "Optional knowledge article ID linked to this notification."}, "email": {"type": "string", "description": "Recipient email address of the notification.", "minLength": 1}, "type": {"type": "string", "enum": ["report", "update", "alert", "reminder", "solution_proposal", "next_steps", "other"], "description": "Type of notification being sent."}}, "required": ["case_id", "email", "type"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260101_043715_660_a8eea1c0_7304e48e", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": {"user_id": 4, "name": "Joanne Simpson", "email": "joanne.simpson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "add_location", "description": "Verify the geographical details for the new location (ID 907).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT city FROM location WHERE location_id = 907;", "expected_value": "london", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_case_knowledge", "description": "Verify the linked knowledge article is published.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT state FROM knowledge WHERE knowledge_id = 209;", "expected_value": "published", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "register_new_installed_product", "description": "Verify the new installed product (ID 301) linking to the location and product.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM installed_product WHERE installed_product_id = 301 AND location_id = 907 AND product_id = 139;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "add_location", "description": "Verify the new London Lab location (ID 907) was created and is active.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM location WHERE location_id = 907 AND name = 'Stark Industries - New Lab' AND active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "register_new_installed_product", "description": "Verify the status of the newly registered installed product (ID 301).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT status FROM installed_product WHERE installed_product_id = 301;", "expected_value": "in_use", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "enlist_new_contract", "description": "Verify the new contract (ID 154) was created and is active for Stark Industries.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract WHERE contract_id = 154 AND account_id = 8 AND status = 'active';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "enlist_new_contract", "description": "Verify the end date for the new contract (ID 154).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT end_date FROM contract WHERE contract_id = 154;", "expected_value": "2026-11-27", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "add_new_entitlement", "description": "Verify the new enterprise 24x7 entitlement (ID 432) for the Juniper product (ID 139) under the new contract.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement WHERE entitlement_id = 432 AND product_id = 139 AND support_level = 'enterprise' AND coverage_hours = 'h24x7';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "add_new_entitlement", "description": "Verify the linked contract (ID 154) and active status for the new entitlement (ID 432).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT contract_id FROM entitlement WHERE entitlement_id = 432;", "expected_value": 154, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case (ID 1233) was created with critical priority and linked to the correct installed product.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE case_id = 1233 AND priority = 'critical' AND installed_product_id = 301;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case details: contact.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT contact_id FROM customer_case WHERE case_id = 1233;", "expected_value": 10, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "assign_case_to_user", "description": "Verify the case was assigned to a specific user within the designated group.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT assigned_to FROM customer_case WHERE case_id = 1233;", "expected_value": 127, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "assign_case_to_user", "description": "Verify the user (ID 127) is a member of the target group (ID 2).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user_group_member WHERE user_id = 127 AND group_id = 2;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_case", "description": "Verify the case was updated to 'in_progress'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT state FROM customer_case WHERE case_id = 1233;", "expected_value": "in_progress", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify the Critical Resolution SLA was successfully applied and is currently in progress.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6 AND stage = 'in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify the linked SLA definition applies to the critical priority.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT applies_to_priority FROM sla_definition WHERE sla_def_id = 6;", "expected_value": "critical", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_case_knowledge", "description": "Verify the troubleshooting guide (ID 209) was linked as 'suggested'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_knowledge WHERE case_id = 1233 AND knowledge_id = 209 AND used_as = 'suggested';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "send_notification", "description": "Verify the solution proposal notification was created for Marc Henry, referencing the case.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM notification WHERE case_id = 1233 AND email = 'marc.henry@stark-industries.com' AND type = 'solution_proposal';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "send_notification", "description": "Verify the notification record links to the correct knowledge article ID (209).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT knowledge_id FROM notification WHERE case_id = 1233 AND email = 'marc.henry@stark-industries.com';", "expected_value": 209, "comparison_type": "equals"}}], "selected_tools": ["find_account", "register_new_installed_product", "find_contacts", "link_case_knowledge", "create_new_case", "find_product", "retrieve_knowledge", "find_user_group", "update_case", "find_entitlements", "add_location", "find_sla_definitions", "enlist_new_contract", "send_notification", "find_user", "list_group_members", "link_new_case_sla", "add_new_entitlement"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "list_group_members": "sn-csm-server", "find_contacts": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "retrieve_knowledge": "sn-csm-server", "add_location": "sn-csm-server", "register_new_installed_product": "sn-csm-server", "enlist_new_contract": "sn-csm-server", "add_new_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "link_case_knowledge": "sn-csm-server", "send_notification": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "There's an SSL termination issue happening on one of Wayne Enterprises' Windows Server boxes, the 2022 Datacenter edition. They called it in, so open a high-priority case for it. Use their primary contact for this, ensuring the contact is active and reachable. Short description: 'SSL termination issue on Windows Server node'. After you've got that case filed, they need renewed coverage since theirs ran out. Set up a new support contract for them, active status, runs all of next year (Jan 1 to Dec 31), price it at 150,000 USD. Under that, add a premium entitlement with full-week availability, letting them open up to 50 cases monthly. Make sure it's for that same server product. Then, find the High-level response SLA, and attach it to this active case. Set everything to show work has started."}], "tools": [{"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "update_contact", "description": "Update a contact (partial updates supported). A contact represents an individual associated with an account, such as a customer representative or point of contact for communication.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact to update."}, "account_id": {"type": "integer", "description": "Account ID to update for this contact."}, "portal_user_id": {"type": "integer", "description": "Updated Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Update the active status of the contact."}, "is_primary": {"type": "boolean", "description": "Update whether this is the primary contact."}}, "required": ["contact_id"]}, "strict": false}, {"type": "function", "name": "enlist_new_contract", "description": "Create a new contract for an account. Contracts define the terms of service, support, or warranty agreements between the organization and its customers.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "ID of the account the contract is associated with."}, "contract_type": {"type": "string", "enum": ["support", "warranty", "subscription"], "description": "Type of contract to create."}, "contract_price": {"type": "integer", "description": "Price value for the contract."}, "status": {"type": "string", "enum": ["draft", "active", "suspended", "expired"], "description": "Initial status of the contract."}, "start_date": {"type": "string", "description": "Start date of the contract (YYYY-MM-DD)."}, "end_date": {"type": "string", "description": "End date of the contract (YYYY-MM-DD)."}}, "required": ["account_id", "contract_type", "status", "start_date", "end_date"]}, "strict": false}, {"type": "function", "name": "add_new_entitlement", "description": "Create a new entitlement. Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID to which the entitlement belongs."}, "product_id": {"type": "integer", "description": "Product ID associated with the entitlement (optional)."}, "contract_id": {"type": "integer", "description": "Contract ID linked to this entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level provided under the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours provided (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month."}, "active": {"type": "boolean", "description": "Indicates whether the entitlement is active (true) or inactive (false)."}}, "required": ["account_id", "support_level", "active"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260101_122222_300_ad5a67e3_3757206c", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": {"user_id": 4, "name": "Joanne Simpson", "email": "joanne.simpson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Confirm the support contract for Wayne Enterprises is created with correct attributes", "description": "Validates the support contract has correct type, status, dates, and price", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract c JOIN account a ON a.account_id = c.account_id WHERE a.name = 'Wayne Enterprises' AND c.contract_type = 'support' AND c.status = 'active' AND c.start_date = '2026-01-01' AND c.end_date = '2026-12-31' AND c.contract_price = 150000;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Confirm the premium 24\u00d77 entitlement exists under Wayne Enterprises with product linkage", "description": "Validates entitlement is linked to the correct product and has correct attributes", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement e JOIN account a ON a.account_id = e.account_id JOIN product p ON e.product_id = p.product_id WHERE a.name = 'Wayne Enterprises' AND e.support_level = 'premium' AND e.coverage_hours = 'h24x7' AND e.max_cases_per_month = 50 AND e.active = 1 AND p.name = 'Windows Server 2022 Datacenter';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Confirm the high-priority phone case was created as NEW then moved to IN_PROGRESS under an active primary contact", "description": "Validates case was created in 'new' state, then updated to 'in_progress', using timestamp evidence. Also verifies contact is active and primary.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN account a ON cc.account_id = a.account_id JOIN contact c ON cc.contact_id = c.contact_id JOIN product p ON cc.product_id = p.product_id WHERE a.name = 'Wayne Enterprises' AND p.name = 'Windows Server 2022 Datacenter' AND cc.short_description = 'SSL termination issue on Windows Server node' AND cc.channel = 'phone' AND cc.priority = 'high' AND cc.state = 'in_progress' AND c.is_primary = 1 AND c.active = 1 AND cc.sys_updated_on > cc.sys_created_on;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Confirm the case is linked to 'SLA Response - High' (RESPONSE metric) and is in_progress", "description": "Validates SLA linkage uses the correct RESPONSE metric SLA (not resolution) and stage is in_progress", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cc.case_id = cs.case_id JOIN sla_definition s ON s.sla_def_id = cs.sla_def_id WHERE cc.short_description = 'SSL termination issue on Windows Server node' AND s.name = 'SLA Response - High' AND s.metric = 'response' AND cs.stage = 'in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Confirm the entitlement is properly linked to the new 2026 support contract", "description": "Validates the entitlement-contract relationship is correctly established", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement e JOIN contract c ON e.contract_id = c.contract_id JOIN account a ON c.account_id = a.account_id WHERE a.name = 'Wayne Enterprises' AND c.contract_type = 'support' AND c.start_date = '2026-01-01' AND e.support_level = 'premium' AND e.coverage_hours = 'h24x7';", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["create_new_case", "find_account", "update_contact", "find_product", "link_new_case_sla", "add_new_entitlement", "find_sla_definitions", "find_contacts", "update_case", "enlist_new_contract"], "restricted_tools": [], "tool_to_gym": {"find_account": "sn-csm-server", "find_product": "sn-csm-server", "find_contacts": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "update_contact": "sn-csm-server", "enlist_new_contract": "sn-csm-server", "add_new_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Perry Watts wrote to us stating that her Atlassian Jira Data Center is not functioning correctly and is impacting her delivery. Register a high priority case for her issue with email as a communication."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contact_by_portal_user", "description": "Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.", "parameters": {"type": "object", "properties": {"portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}}, "required": ["portal_user_id"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_knowledge", "description": "Retrieve knowledge articles with full-text search on title/body and structured filters. All inputs are optional; not providing any filter will return all knowledge articles. A knowledge article is a documented piece of information that provides solutions, answers, or guidance on specific topics to help users resolve issues or learn about products and services.", "parameters": {"type": "object", "properties": {"search_text": {"type": "string", "description": "Full-text search across article title and body. Free form search."}, "knowledge_id": {"type": "integer", "description": "Filter by unique knowledge article ID."}, "kb_number": {"type": "string", "description": "Filter by knowledge base number."}, "title": {"type": "string", "description": "Filter by article title."}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Filter by article lifecycle state."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Filter by article visibility. Internal for staff, external for customers/public."}, "product_id": {"type": "integer", "description": "Filter by related product ID."}, "owner_id": {"type": "integer", "description": "Filter by user ID of the article owner. User who authored the article."}, "created_before": {"type": "string", "description": "Retrieve articles created before this timestamp."}, "created_after": {"type": "string", "description": "Retrieve articles created after this timestamp."}, "limit": {"type": "integer", "description": "Limit the number of articles returned."}}}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260102_155148_014_accab84d_910b176a", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "karen.watkins@servicenow.com"}, "user_info": {"user_id": 39, "name": "Karen Watkins", "email": "karen.watkins@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "High priority case created for Perry Watts", "description": "High priority case created for Perry Watts", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_created\nFROM customer_case\nWHERE case_id = 1233\n AND account_id = 30\n AND contact_id = 64\n AND product_id = 17\n AND channel = 'email'\n AND priority = 'high';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify KB article is linked to the case", "description": "Verify KB article is linked to the case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_kb_link_exists\nFROM case_knowledge\nWHERE case_id = 1233\n AND knowledge_id = 27\n AND used_as = 'suggested';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify SLA Definition (Response - High) Exists", "description": "Verify SLA Definition (Response - High) Exists", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS sla_def_response_exists\nFROM sla_definition\nWHERE sla_def_id = 2\n AND name = 'SLA Response - High'\n AND metric = 'response'", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify SLA Definition (Resolution - High) Exists", "description": "Verify SLA Definition (Resolution - High) Exists", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS sla_def_resolution_exists\nFROM sla_definition\nWHERE sla_def_id = 7\n AND name = 'SLA Resolution - High'\n AND metric = 'resolution';", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_entitlements", "link_case_knowledge", "update_case", "create_new_case", "retrieve_knowledge", "find_user", "find_product", "find_sla_definitions", "find_contact_by_portal_user", "link_new_case_sla"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_contact_by_portal_user": "sn-csm-server", "find_product": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "retrieve_knowledge": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "link_case_knowledge": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "So Larson PLC is setting up in the UK - they need a location registered as 'Larson London Office' in London. Elsa Larson should be their go-to person and needs access to the customer portal. Use elsa.larson@larsonplc.com and +44-20-3000-6000. They've installed SUSE Linux Enterprise Server 15 at that office. Serial: LAR-SLES-2027. It's under warranty until June thirtieth, twenty twenty-seven. Put them on a premium support contract for next year, full year coverage at one hundred twenty thousand dollars. High-end support, available all hours, but cap it at twenty cases a month. Elsa reached out via phone about getting that SLES box configured - it's moderately urgent. Get someone working on it now, don't just create it and leave it sitting there. Apply the standard response SLA for that urgency tier and mark it as currently running. Document this as 'SLES Setup Guide' for that specific server product - internal use only. Whoever's been with the company longest (whether they're a regular agent or manager, either's fine) from the same country Larson operates in should own it. Put this in: 'Group: Larson Operations Desk. Assigned: group manager. Steps: repo check, patch, reboot.' Tag that doc as the solution to Elsa's issue. Make sure we have a 'Larson Operations Desk' team set up and include Elsa on it. Send her the solution proposal."}], "tools": [{"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "list_users", "description": "List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned.", "parameters": {"type": "object", "properties": {"email": {"type": "string", "description": "Filter by user email address (exact match) (unique)."}, "user_id": {"type": "integer", "description": "Filter by unique user identifier."}, "first_name": {"type": "string", "description": "Filter by user's first name."}, "last_name": {"type": "string", "description": "Filter by user's last name."}, "phone": {"type": "string", "description": "Filter by phone number."}, "role": {"type": "string", "enum": ["admin", "agent", "manager", "customer"], "description": "Filter by user role (admin, agent, manager, or customer)."}, "location_id": {"type": "integer", "description": "Filter by location identifier."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "created_after": {"type": "string", "description": "Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "add_new_user", "description": "Create a new user record. A user represents an individual who interacts with the system, such as support agents, managers, or customers.", "parameters": {"type": "object", "properties": {"first_name": {"type": "string", "description": "User's first name.", "minLength": 1}, "last_name": {"type": "string", "description": "User's last name.", "minLength": 1}, "email": {"type": "string", "description": "Unique email address of the user.", "minLength": 1}, "phone": {"type": "string", "description": "Contact phone number of the user."}, "role": {"type": "string", "enum": ["admin", "agent", "manager", "customer"], "description": "User role within the system."}, "location_id": {"type": "integer", "description": "Associated location identifier. Optional. Location where user resides/works."}, "active": {"type": "boolean", "description": "Whether the user is active (true) or inactive (false)."}}, "required": ["first_name", "last_name", "email", "role", "active"]}, "strict": false}, {"type": "function", "name": "add_new_user_group", "description": "Create a user group. A user group is a collection of users who share similar roles, responsibilities, or access permissions within the system, allowing for efficient management and assignment of tasks or cases.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Name of the user group.", "minLength": 1}, "type": {"type": "string", "enum": ["support", "backoffice", "field", "vendor"], "description": "Type of the user group (support, backoffice, field, vendor)."}, "active": {"type": "boolean", "description": "Whether the group is active (true) or inactive (false)."}}, "required": ["name", "type", "active"]}, "strict": false}, {"type": "function", "name": "add_new_group_member", "description": "Add a user to a group. Combination of group_id and user_id should be unique.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Identifier of the group the user will be added to."}, "user_id": {"type": "integer", "description": "Identifier of the user being added to the group."}}, "required": ["group_id", "user_id"]}, "strict": false}, {"type": "function", "name": "create_contact", "description": "Create a new contact. A contact represents an individual associated with an account, such as a customer representative or point of contact for communication.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "ID of the account the contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is active upon creation."}, "is_primary": {"type": "boolean", "description": "Set to true if this contact should be the account's primary contact."}}, "required": ["account_id", "portal_user_id", "active", "is_primary"]}, "strict": false}, {"type": "function", "name": "add_location", "description": "Create a new location (site). A location represents a physical site or office associated with the organization, such as branch offices, warehouses, or service centers.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Name of the location/site (e.g., 'Downtown HQ').", "minLength": 1}, "active": {"type": "boolean", "description": "Whether the location is active (true) or inactive (false)."}, "plot_no": {"type": "string", "description": "Plot number of the location (optional)."}, "street": {"type": "string", "description": "Street address of the location (optional)."}, "city": {"type": "string", "enum": ["new_york", "london", "mumbai", "tokyo", "sydney"], "description": "City where the location is situated."}, "country": {"type": "string", "enum": ["usa", "uk", "india", "japan", "australia"], "description": "Country where the location is situated."}}, "required": ["name", "active", "city", "country"]}, "strict": false}, {"type": "function", "name": "register_new_installed_product", "description": "Register a new installed product at an account/location. Combination of Account ID, Product ID, Serial Number should be unique.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Location/site ID where the product is installed."}, "account_id": {"type": "integer", "description": "Owning account ID for this installed product."}, "product_id": {"type": "integer", "description": "Product ID that was installed."}, "serial_number": {"type": "string", "description": "Unique serial number of the installed product.", "minLength": 1}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Status of the installed product."}, "warranty_end": {"type": "string", "description": "Warranty end date (YYYY-MM-DD)."}}, "required": ["account_id", "product_id", "serial_number", "status"]}, "strict": false}, {"type": "function", "name": "enlist_new_contract", "description": "Create a new contract for an account. Contracts define the terms of service, support, or warranty agreements between the organization and its customers.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "ID of the account the contract is associated with."}, "contract_type": {"type": "string", "enum": ["support", "warranty", "subscription"], "description": "Type of contract to create."}, "contract_price": {"type": "integer", "description": "Price value for the contract."}, "status": {"type": "string", "enum": ["draft", "active", "suspended", "expired"], "description": "Initial status of the contract."}, "start_date": {"type": "string", "description": "Start date of the contract (YYYY-MM-DD)."}, "end_date": {"type": "string", "description": "End date of the contract (YYYY-MM-DD)."}}, "required": ["account_id", "contract_type", "status", "start_date", "end_date"]}, "strict": false}, {"type": "function", "name": "add_new_entitlement", "description": "Create a new entitlement. Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID to which the entitlement belongs."}, "product_id": {"type": "integer", "description": "Product ID associated with the entitlement (optional)."}, "contract_id": {"type": "integer", "description": "Contract ID linked to this entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level provided under the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours provided (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month."}, "active": {"type": "boolean", "description": "Indicates whether the entitlement is active (true) or inactive (false)."}}, "required": ["account_id", "support_level", "active"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "create_knowledge", "description": "Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.", "parameters": {"type": "object", "properties": {"title": {"type": "string", "description": "Title of the knowledge article.", "minLength": 1}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Lifecycle state of the article."}, "body": {"type": "string", "description": "Body of the knowledge article."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Who can view the article: internal staff or external customers."}, "product_id": {"type": "integer", "description": "ID of the related product, if applicable."}, "owner_id": {"type": "integer", "description": "User ID of the article owner/author."}}, "required": ["title", "state", "body", "visibility", "owner_id"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}, {"type": "function", "name": "send_notification", "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Case ID this notification is related to."}, "knowledge_id": {"type": "integer", "description": "Optional knowledge article ID linked to this notification."}, "email": {"type": "string", "description": "Recipient email address of the notification.", "minLength": 1}, "type": {"type": "string", "enum": ["report", "update", "alert", "reminder", "solution_proposal", "next_steps", "other"], "description": "Type of notification being sent."}}, "required": ["case_id", "email", "type"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260102_161510_799_ad5a67e3_7221f3c8", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": {"user_id": 4, "name": "Joanne Simpson", "email": "joanne.simpson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verify the SUSE product exists", "description": "Verify SUSE Linux Enterprise Server 15 exists and is active", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM product WHERE name = 'SUSE Linux Enterprise Server 15' AND lifecycle_state = 'active';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the Larson PLC account exists", "description": "Verify the Larson PLC account exists and is active", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM account WHERE name = 'Larson PLC' AND active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the London location for Larson PLC exists", "description": "Verify the London location for Larson PLC exists", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM location WHERE name = 'Larson London Office' AND city = 'london' AND country = 'uk' AND active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the portal user for Elsa Larson", "description": "Verify the portal user Elsa Larson exists with correct attributes", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user WHERE email = 'elsa.larson@larsonplc.com' AND first_name = 'Elsa' AND last_name = 'Larson' AND role = 'customer' AND active = 1 AND phone = '+44-20-3000-6000';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the Elsa Larson contact", "description": "Verify the Elsa Larson contact is created for Larson PLC and set as primary", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contact c JOIN account a ON c.account_id = a.account_id JOIN user u ON c.portal_user_id = u.user_id WHERE a.name = 'Larson PLC' AND u.email = 'elsa.larson@larsonplc.com' AND c.active = 1 AND c.is_primary = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the SUSE installed product record", "description": "Verify the SUSE installed product record", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM installed_product ip JOIN account a ON ip.account_id = a.account_id JOIN product p ON ip.product_id = p.product_id JOIN location l ON ip.location_id = l.location_id WHERE a.name = 'Larson PLC' AND p.name = 'SUSE Linux Enterprise Server 15' AND l.name = 'Larson London Office' AND ip.serial_number = 'LAR-SLES-2027' AND ip.status = 'in_use' AND ip.warranty_end = '2027-06-30';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the support contract for 2026", "description": "Verify the support contract for 2026", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM contract c JOIN account a ON c.account_id = a.account_id WHERE a.name = 'Larson PLC' AND c.contract_type = 'support' AND c.status = 'active' AND c.start_date = '2026-01-01' AND c.end_date = '2026-12-31' AND c.contract_price = 120000;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the premium 24x7 entitlement", "description": "Verify the premium 24x7 entitlement", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement e JOIN account a ON e.account_id = a.account_id WHERE a.name = 'Larson PLC' AND e.support_level = 'premium' AND e.coverage_hours = 'h24x7' AND e.max_cases_per_month = 20 AND e.active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the case and its SLA linkage", "description": "Verify the case and its SLA linkage", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN account a ON cc.account_id = a.account_id JOIN case_sla cs ON cc.case_id = cs.case_id JOIN sla_definition s ON s.sla_def_id = cs.sla_def_id WHERE a.name = 'Larson PLC' AND cc.case_id = 1233 AND cc.assignment_group_id = 81 AND cc.assigned_to = 217 AND cc.channel = 'phone' AND cc.priority = 'moderate' AND cc.state = 'in_progress' AND s.name = 'SLA Response - Moderate' AND cs.stage = 'in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the knowledge article exists", "description": "Verify the knowledge article exists with the correct attributes", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM knowledge k JOIN product p ON k.product_id = p.product_id WHERE k.title = 'SLES Setup Guide' AND k.state = 'published' AND k.owner_id = 152 AND k.visibility = 'internal' AND p.name = 'SUSE Linux Enterprise Server 15';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the knowledge article was correctly linked to the case as a resolution", "description": "Verify the knowledge article was correctly linked to the case as a resolution", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_knowledge ck JOIN knowledge k ON ck.knowledge_id = k.knowledge_id JOIN customer_case cc ON ck.case_id = cc.case_id WHERE k.title = 'SLES Setup Guide' AND k.owner_id = 152 AND ck.used_as = 'resolution';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the Larson Operations Desk group exists", "description": "Verify the support assignment group was created", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user_group WHERE name = 'Larson Operations Desk' AND type = 'support' AND active = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Elsa Larson is a member of Larson Operations Desk", "description": "Verify group membership was added for Elsa", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user_group_member ugm JOIN user_group g ON ugm.group_id = g.group_id JOIN user u ON ugm.user_id = u.user_id WHERE g.name = 'Larson Operations Desk' AND u.email = 'elsa.larson@larsonplc.com';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify the solution proposal notification was sent", "description": "Verify a solution_proposal notification was sent successfully to Elsa for the case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM notification n JOIN customer_case cc ON n.case_id = cc.case_id WHERE n.email = 'elsa.larson@larsonplc.com' AND n.type = 'solution_proposal' AND n.status = 'success';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify KB owner selection rule (min +44 agent/manager)", "description": "Verify the knowledge owner is the active agent/manager with the smallest user_id and phone starting with +44", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM knowledge k JOIN user u ON k.owner_id = u.user_id WHERE k.title = 'SLES Setup Guide' AND k.owner_id = 152 AND u.active = 1 AND u.role IN ('agent','manager') AND u.phone LIKE '+44%' AND u.user_id = (SELECT MIN(user_id) FROM user WHERE active = 1 AND role IN ('agent','manager') AND phone LIKE '+44%');", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_sla_definitions", "add_location", "add_new_entitlement", "register_new_installed_product", "create_knowledge", "create_contact", "create_new_case", "find_product", "link_new_case_sla", "link_case_knowledge", "add_new_group_member", "add_new_user", "find_account", "list_users", "update_case", "enlist_new_contract", "find_entitlements", "send_notification", "add_new_user_group"], "restricted_tools": [], "tool_to_gym": {"find_account": "sn-csm-server", "find_product": "sn-csm-server", "list_users": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "add_new_user": "sn-csm-server", "add_new_user_group": "sn-csm-server", "add_new_group_member": "sn-csm-server", "create_contact": "sn-csm-server", "add_location": "sn-csm-server", "register_new_installed_product": "sn-csm-server", "enlist_new_contract": "sn-csm-server", "add_new_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "create_knowledge": "sn-csm-server", "link_case_knowledge": "sn-csm-server", "send_notification": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Umbrella's Tokyo office has rolled out a new Red Hat Enterprise Linux 9 node (serial RHEL-UMB-4500) and it's crashing frequently. Ensure our records reflect the environment and that support is initiated appropriately: the install should be registered to Umbrella with warranty through 31-Dec-2026; Travis Wood should have access via the Proactive Case Monitoring group for oversight; and the issue should be captured as a high-priority phone case titled 'Product: Red Hat Enterprise Linux 9, Issue: node crashes frequently.' under Umbrella's primary contact, linked to the new install and product, and governed by the active high response sla with tracking started. Update everything accordingly."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_locations", "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Unique identifier of the location."}, "name": {"type": "string", "description": "Name of the location."}, "active": {"type": "boolean", "description": "Whether the location is currently active."}, "plot_no": {"type": "string", "description": "Plot number of the location."}, "street": {"type": "string", "description": "Street address of the location."}, "city": {"type": "string", "description": "City where the location is situated."}, "country": {"type": "string", "description": "Country where the location is situated."}, "created_before": {"type": "string", "description": "Filter for locations created before this timestamp (ISO format)."}, "created_after": {"type": "string", "description": "Filter for locations created after this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "add_new_group_member", "description": "Add a user to a group. Combination of group_id and user_id should be unique.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Identifier of the group the user will be added to."}, "user_id": {"type": "integer", "description": "Identifier of the user being added to the group."}}, "required": ["group_id", "user_id"]}, "strict": false}, {"type": "function", "name": "register_new_installed_product", "description": "Register a new installed product at an account/location. Combination of Account ID, Product ID, Serial Number should be unique.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Location/site ID where the product is installed."}, "account_id": {"type": "integer", "description": "Owning account ID for this installed product."}, "product_id": {"type": "integer", "description": "Product ID that was installed."}, "serial_number": {"type": "string", "description": "Unique serial number of the installed product.", "minLength": 1}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Status of the installed product."}, "warranty_end": {"type": "string", "description": "Warranty end date (YYYY-MM-DD)."}}, "required": ["account_id", "product_id", "serial_number", "status"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260102_172945_725_ad5a67e3_5480e26f", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": {"user_id": 4, "name": "Joanne Simpson", "email": "joanne.simpson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verifier 1 - Verify installed product registration at Umbrella's Tokyo site", "description": "Verify that the installed product record was created at Umbrella's Tokyo site with the expected values", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM installed_product ip JOIN account a ON ip.account_id=a.account_id JOIN product p ON ip.product_id=p.product_id JOIN location l ON ip.location_id=l.location_id WHERE a.name='Umbrella' AND p.name='Red Hat Enterprise Linux 9' AND l.name='Umbrella Site A - Tokyo' AND ip.serial_number='RHEL-UMB-4500' AND ip.status='in_use' AND ip.warranty_end='2026-12-31';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verifier 2 - Verify Travis Wood group membership", "description": "Verify that Travis Wood was added to the Proactive Case Monitoring group", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM user_group_member gm JOIN user u ON gm.user_id=u.user_id JOIN user_group g ON gm.group_id=g.group_id WHERE u.first_name='Travis' AND u.last_name='Wood' AND g.name='Proactive Case Monitoring';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verifier 3 - Verify case with active primary contact", "description": "Verify that the case exists, is linked to an active primary contact, product and install, and uses the correct channel, priority and description", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN account a ON cc.account_id=a.account_id JOIN product p ON cc.product_id=p.product_id JOIN installed_product ip ON cc.installed_product_id=ip.installed_product_id JOIN contact c ON cc.contact_id=c.contact_id WHERE a.name='Umbrella' AND p.name='Red Hat Enterprise Linux 9' AND ip.serial_number='RHEL-UMB-4500' AND cc.short_description= 'Product: Red Hat Enterprise Linux 9, Issue: node crashes frequently.' AND cc.channel='phone' AND cc.priority='high' AND c.is_primary=1 AND c.active=1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verifier 4 - Verify SLA linkage and tracking", "description": "Verify that the case is linked to the correct SLA and tracking is in progress", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cc.case_id=cs.case_id JOIN sla_definition s ON s.sla_def_id=cs.sla_def_id WHERE cc.short_description='Product: Red Hat Enterprise Linux 9, Issue: node crashes frequently.' AND s.name='SLA Response - High' AND s.metric='response' AND cs.stage='in_progress';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verifier 5 - Verify case state transition to in_progress", "description": "Verify that the case was created in new state then moved to in_progress (timestamp evidence)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN account a ON cc.account_id=a.account_id WHERE a.name='Umbrella' AND cc.short_description='Product: Red Hat Enterprise Linux 9, Issue: node crashes frequently.' AND cc.state='in_progress' AND cc.sys_updated_on > cc.sys_created_on;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["register_new_installed_product", "link_new_case_sla", "create_new_case", "find_locations", "find_contacts", "find_user", "find_user_group", "add_new_group_member", "find_product", "find_account", "update_case", "find_sla_definitions"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "find_contacts": "sn-csm-server", "find_locations": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "add_new_group_member": "sn-csm-server", "register_new_installed_product": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Michael Ward said in a chat that he is currently facing an issue with MySQL Enterprise 8.0 Variant 28 as it restarts after the update. Create a new case on this with high priority and have Robin Monroe investigate it immediately and link suggested article for agent if there is any. Also, assign this to the Case Assignment_3 group. Finally, send a notification to the user about case creation report."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contact_by_portal_user", "description": "Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.", "parameters": {"type": "object", "properties": {"portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}}, "required": ["portal_user_id"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "check_user_membership", "description": "Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"user_id": {"type": "integer", "description": "User's unique id to check"}, "group_id": {"type": "integer", "description": "User group's unique id to check"}}, "required": ["user_id", "group_id"]}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_knowledge", "description": "Retrieve knowledge articles with full-text search on title/body and structured filters. All inputs are optional; not providing any filter will return all knowledge articles. A knowledge article is a documented piece of information that provides solutions, answers, or guidance on specific topics to help users resolve issues or learn about products and services.", "parameters": {"type": "object", "properties": {"search_text": {"type": "string", "description": "Full-text search across article title and body. Free form search."}, "knowledge_id": {"type": "integer", "description": "Filter by unique knowledge article ID."}, "kb_number": {"type": "string", "description": "Filter by knowledge base number."}, "title": {"type": "string", "description": "Filter by article title."}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Filter by article lifecycle state."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Filter by article visibility. Internal for staff, external for customers/public."}, "product_id": {"type": "integer", "description": "Filter by related product ID."}, "owner_id": {"type": "integer", "description": "Filter by user ID of the article owner. User who authored the article."}, "created_before": {"type": "string", "description": "Retrieve articles created before this timestamp."}, "created_after": {"type": "string", "description": "Retrieve articles created after this timestamp."}, "limit": {"type": "integer", "description": "Limit the number of articles returned."}}}, "strict": false}, {"type": "function", "name": "add_new_group_member", "description": "Add a user to a group. Combination of group_id and user_id should be unique.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Identifier of the group the user will be added to."}, "user_id": {"type": "integer", "description": "Identifier of the user being added to the group."}}, "required": ["group_id", "user_id"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}, {"type": "function", "name": "send_notification", "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Case ID this notification is related to."}, "knowledge_id": {"type": "integer", "description": "Optional knowledge article ID linked to this notification."}, "email": {"type": "string", "description": "Recipient email address of the notification.", "minLength": 1}, "type": {"type": "string", "enum": ["report", "update", "alert", "reminder", "solution_proposal", "next_steps", "other"], "description": "Type of notification being sent."}}, "required": ["case_id", "email", "type"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20260104_202644_765_00364ece_a86667c0", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "scott.mitchell@servicenow.com"}, "user_info": {"user_id": 41, "name": "Scott Mitchell", "email": "scott.mitchell@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verify knowledge is attached", "description": "Verify that the relevant knowledge article is attached with case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_knowledge WHERE case_id = 1233 AND knowledge_id = 70;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Validating whether assigned user is present in the assigned group. ", "description": "Validating whether Robin Monroe is present in Case Assignment_3 group.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count\nFROM user u\nJOIN user_group_member ugm ON u.user_id = ugm.user_id\nJOIN user_group g ON g.group_id = ugm.group_id\nWHERE u.first_name = 'Robin'\n AND u.last_name = 'Monroe'\n AND g.name = 'Case Assignment_3';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Validating whether new case has been created. ", "description": "Validating whether a new case for Michael Ward, product MySQL Enterprise 8.0 Variant 28, through chat, high priority, assigned to Robin Monroe, assigned to Case Assignment_3 group is created.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count\nFROM customer_case c\nJOIN product p ON c.product_id = p.product_id\nJOIN contact ct ON c.contact_id = ct.contact_id\nJOIN user u ON ct.portal_user_id = u.user_id\nJOIN user assigned ON c.assigned_to = assigned.user_id\nJOIN user_group g ON c.assignment_group_id = g.group_id\nWHERE u.first_name = 'Michael'\n AND u.last_name = 'Ward'\n AND p.name = 'MySQL Enterprise 8.0 Variant 28'\n AND c.channel = 'chat'\n AND c.priority = 'high'\n AND c.state = 'in_progress'\n AND assigned.first_name = 'Robin'\n AND assigned.last_name = 'Monroe'\n AND g.name = 'Case Assignment_3';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Validate Notification", "description": "Validating whether a Case report notification sent to Michael Ward", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count\nFROM notification n\nJOIN user u ON n.email = u.email\nWHERE u.first_name = 'Michael'\n AND u.last_name = 'Ward'\n AND n.type = 'report'\n AND n.status = 'success'\n AND n.case_id = 1233;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify that Response SLA is attached", "description": "Verify that High priority response sla is attached to case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND sla_def_id = 2;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify that Resolution SLA is attached", "description": "Verify that High priority resolution sla is attached to case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND sla_def_id = 7;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_product", "find_user", "add_new_group_member", "create_new_case", "send_notification", "find_user_group", "check_user_membership", "update_case", "find_contact_by_portal_user", "retrieve_knowledge", "find_sla_definitions", "link_new_case_sla", "find_entitlements", "link_case_knowledge"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_contact_by_portal_user": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "check_user_membership": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "retrieve_knowledge": "sn-csm-server", "add_new_group_member": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "link_case_knowledge": "sn-csm-server", "send_notification": "sn-csm-server"}}}
diff --git a/resources_servers/enterpriseops_gym/data/example.jsonl b/resources_servers/enterpriseops_gym/data/example.jsonl
new file mode 100644
index 0000000000..5934ac68da
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/example.jsonl
@@ -0,0 +1,5 @@
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Marc Henry needs to address a critical situation for Stark Industries. Update the existing entitlement for their Palo Alto Networks PA-3220 Variant 8 to our highest Enterprise support level, ensuring 24x7 coverage and removing any monthly case limits. Register a new critical case for this device, reporting that the Dataplane crashes repeatedly, using the phone channel. Assign the case to Curtis McCoy and the Escalation Management group. Ensure the mandatory Resolution SLA is applied to this case."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_contact_by_portal_user", "description": "Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.", "parameters": {"type": "object", "properties": {"portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}}, "required": ["portal_user_id"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "update_entitlement", "description": "Update an entitlement (partial updates allowed). Entitlements define the support and service levels provided to an account for specific products or contracts.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique ID of the entitlement to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "product_id": {"type": "integer", "description": "Update the product ID linked to the entitlement."}, "contract_id": {"type": "integer", "description": "Update the contract ID linked to the entitlement."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Update the support level."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Update the coverage hours."}, "max_cases_per_month": {"type": "integer", "description": "Update the maximum number of support cases per month."}, "active": {"type": "boolean", "description": "Set entitlement status as active (true) or inactive (false)."}}, "required": ["entitlement_id"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251205_153330_906_a8eea1c0_8c7a6205", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "joanne.simpson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's coverage hours were updated to h24x7.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "expected_value": "h24x7", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's max case limit was set to unlimited (0).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT max_cases_per_month FROM entitlement WHERE entitlement_id = 73;", "expected_value": 0, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify that Entitlement 73's update timestamp is newer than its original data record to confirm the update occurred.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM entitlement WHERE entitlement_id = 73 AND sys_updated_on IS NOT NULL", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the new case (ID 1233) was created for the correct installed product (ID 42).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT installed_product_id FROM customer_case WHERE case_id = 1233;", "expected_value": 42, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the new case priority is 'critical' and channel is 'phone'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT priority FROM customer_case WHERE case_id = 1233 AND channel = 'phone';", "expected_value": "critical", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case (ID 1233) was correctly assigned to the Escalation Management group (ID 18).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT assignment_group_id FROM customer_case WHERE case_id = 1233;", "expected_value": 18, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case (ID 1233) was correctly assigned to Curtis McCoy (ID 177).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT assigned_to FROM customer_case WHERE case_id = 1233;", "expected_value": 177, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_new_case", "description": "Verify the case initial state was correctly set to 'in_progress'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT state FROM customer_case WHERE case_id = 1233;", "expected_value": "in_progress", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify that the Critical Resolution SLA (ID 6) was linked to the new case (ID 1233).", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "link_new_case_sla", "description": "Verify that the new case_sla entry's stage is set to 'in_progress'.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT stage FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;", "expected_value": "in_progress", "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "update_entitlement", "description": "Verify Entitlement 73's support level was updated to enterprise.", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT support_level FROM entitlement WHERE entitlement_id = 73;", "expected_value": "enterprise", "comparison_type": "equals"}}], "selected_tools": ["find_user_group", "retrieve_installed_products", "update_case", "update_entitlement", "find_contact_by_portal_user", "find_sla_definitions", "find_entitlements", "find_user", "find_product", "link_new_case_sla", "create_new_case"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_contact_by_portal_user": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "update_entitlement": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management assistant. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, ing record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account\u2019s data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) Default state = new. Verify the product or installed product belongs to the customer\u2019s account.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group. Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user\u2019s relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product\u2019s product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer\u2019s entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "During our December 5th, 2025 review of the London setup, we noticed that the facility with the older plot and curve address pattern in the 90s area is being reorganized. One of the P25-serial type devices at that location needs its records updated, and the device's warranty window is coming up soon.\nPlease update the system by relocating this device to the London site with the newer plot and street configuration, specifically the one on the Pratt Curve side, and ensure its status remains operational. After completing the update, please send a notification to the associated account contacts for this product so they're aware of the change."}], "tools": [{"type": "function", "name": "list_users", "description": "List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned.", "parameters": {"type": "object", "properties": {"email": {"type": "string", "description": "Filter by user email address (exact match) (unique)."}, "user_id": {"type": "integer", "description": "Filter by unique user identifier."}, "first_name": {"type": "string", "description": "Filter by user's first name."}, "last_name": {"type": "string", "description": "Filter by user's last name."}, "phone": {"type": "string", "description": "Filter by phone number."}, "role": {"type": "string", "enum": ["admin", "agent", "manager", "customer"], "description": "Filter by user role (admin, agent, manager, or customer)."}, "location_id": {"type": "integer", "description": "Filter by location identifier."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "created_after": {"type": "string", "description": "Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_locations", "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Unique identifier of the location."}, "name": {"type": "string", "description": "Name of the location."}, "active": {"type": "boolean", "description": "Whether the location is currently active."}, "plot_no": {"type": "string", "description": "Plot number of the location."}, "street": {"type": "string", "description": "Street address of the location."}, "city": {"type": "string", "description": "City where the location is situated."}, "country": {"type": "string", "description": "Country where the location is situated."}, "created_before": {"type": "string", "description": "Filter for locations created before this timestamp (ISO format)."}, "created_after": {"type": "string", "description": "Filter for locations created after this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "update_installed_product_details", "description": "Update an installed product (partial updates allowed). Combination of Account ID, Product ID, Serial Number should be unique.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID (required)."}, "location_id": {"type": "integer", "description": "Location/site ID where the product is installed."}, "account_id": {"type": "integer", "description": "Owning account ID for this installed product."}, "product_id": {"type": "integer", "description": "Product ID that was installed."}, "serial_number": {"type": "string", "description": "Unique serial number of the installed product.", "minLength": 1}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Status of the installed product."}, "warranty_end": {"type": "string", "description": "Warranty end date (YYYY-MM-DD)."}}, "required": ["installed_product_id"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "send_notification", "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Case ID this notification is related to."}, "knowledge_id": {"type": "integer", "description": "Optional knowledge article ID linked to this notification."}, "email": {"type": "string", "description": "Recipient email address of the notification.", "minLength": 1}, "type": {"type": "string", "enum": ["report", "update", "alert", "reminder", "solution_proposal", "next_steps", "other"], "description": "Type of notification being sent."}}, "required": ["case_id", "email", "type"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251205_154853_044_d4a463c3_fce76046", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "Verify Updated Installed Product", "description": "Verify Updated Installed Product", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) \nFROM installed_product AS ip\nWHERE ip.installed_product_id = 40\n AND ip.location_id = 692\n AND ip.status = 'in_use';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Create New Case", "description": "Verify Create New Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM customer_case AS c\nWHERE c.account_id = 8\n AND c.contact_id = 10\n AND c.channel = 'alert'\n AND c.priority = 'low'\n AND c.state = 'closed';\n ", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Notification Sent ", "description": "Verify Notification Sent ", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'marc.henry@stark-industries.com'\n AND n.type = 'update';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Notification Sent ", "description": "Verify Notification Sent ", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'tonya.stevens@stark-industries.com'\n AND n.type = 'update';\n", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["update_case", "send_notification", "create_new_case", "find_locations", "find_contacts", "update_installed_product_details", "list_users", "retrieve_installed_products"], "restricted_tools": [], "tool_to_gym": {"list_users": "sn-csm-server", "find_contacts": "sn-csm-server", "find_locations": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "update_installed_product_details": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "send_notification": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "The Wilson and Sons customer reached out via email, explaining that they had previously logged a case that was closed on 2nd October 2025 for their Managed Network Services asset but was eventually canceled. The issue is still ongoing, and they now want the case recreated and also mentioned that they want to escalate this since the problem has persisted for too long. Please open a case using the same contact, product, issue description, and priority from the canceled one, set the channel to email, assign it to the Case Assignment_2 team, and allocate it to agent Cory Vargas. Once the case is created, confirm that the entitlement is active and attach all SLAs appropriate for the priority level."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product", "description": "Look up a product by its exact name. Product represents an item or service offered by the company.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Product name, e.g., 'Pulse Edge'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_user_group", "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact name of the user group (unique).", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "check_user_membership", "description": "Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes.", "parameters": {"type": "object", "properties": {"user_id": {"type": "integer", "description": "User's unique id to check"}, "group_id": {"type": "integer", "description": "User group's unique id to check"}}, "required": ["user_id", "group_id"]}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "search_cases", "description": "Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case."}, "number": {"type": "string", "description": "Case number (unique human-readable reference)."}, "account_id": {"type": "integer", "description": "Filter by account ID. An account represents a business entity or organization."}, "contact_id": {"type": "integer", "description": "Filter by contact ID."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "installed_product_id": {"type": "integer", "description": "Filter by installed product ID. Unique identifier which relates to the installed product table record."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was communicated/created."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "State of the case."}, "short_description": {"type": "string", "description": "Short description of the case."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation."}, "reopen_count": {"type": "integer", "description": "Filter by number of times the case was reopened."}, "closed_on": {"type": "string", "description": "Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return cases created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251209_132736_542_99ba2325_6705caf4", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1765219280033_d7pqrz32b.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": {"user_id": 32, "name": "Jose Roberson", "email": "jose.roberson@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verify case creation", "description": "Verify case creation", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM customer_case WHERE case_id = 1233 AND state = 'in_progress' AND assignment_group_id = 24 AND assigned_to = 427 AND channel = 'email' AND priority = 'critical' AND escalation_reason = 'customer_request' AND escalation = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify group membership", "description": "Verify group membership", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM user_group_member WHERE group_id = 24 AND user_id = 427;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify case sla 1", "description": "Verify case sla 1", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 1;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify case sla 2", "description": "Verify case sla 2", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 6;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_user_group", "update_case", "find_user", "find_entitlements", "find_contacts", "link_new_case_sla", "find_sla_definitions", "search_cases", "check_user_membership", "find_product", "find_account", "create_new_case"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "find_product": "sn-csm-server", "find_user_group": "sn-csm-server", "check_user_membership": "sn-csm-server", "find_contacts": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "search_cases": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "Klein Black and Wood's India facility reported via community post that their Dell rack server keeps hitting kernel panics. I forgot to note the machine's serial, but I remember it wraps up with the digits 9300. Log this at mid-range priority through the community channel using their lead site contact. Pass it to the first foundation-level installed product support squad. Bind a response timer appropriate for that priority bracket. If possible, pick one that doesn't freeze during customer wait states. Get that timer ticking, but the case should show initial registration status, not active work if it's possible. The description must read 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' exactly as written."}], "tools": [{"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_product_by_id", "description": "Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id.", "parameters": {"type": "object", "properties": {"product_id": {"type": "integer", "description": " Unique identifier of the product."}}, "required": ["product_id"]}, "strict": false}, {"type": "function", "name": "list_user_groups", "description": "List user groups with optional filters.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Filter by unique group identifier."}, "name": {"type": "string", "description": "Filter by group name (exact match, unique)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "type": {"type": "string", "enum": ["support", "backoffice", "field", "vendor"], "description": "Filter by group type (support, backoffice, field, vendor)."}, "created_after": {"type": "string", "description": "Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "get_accounts", "description": "List accounts with optional filters. All the inputs are optional, not providing any filter will return all accounts. Account represents a business entity or organization.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Filter by unique account identifier."}, "name": {"type": "string", "description": "Filter by account name (e.g., 'Acme Systems') (unique). Name of the company/organization associated with the account.", "minLength": 1}, "email_domain": {"type": "string", "description": "Filter by account email domain (e.g., 'acme.com'). it is the domain part of email addresses associated with the account or the website.", "minLength": 1}, "account_types": {"type": "array", "items": {"type": "string", "enum": ["customer", "partner", "internal"]}, "description": "Filter by one or more account types (customer, partner, internal)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "created_after": {"type": "string", "description": "Return only accounts created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only accounts created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_locations", "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.", "parameters": {"type": "object", "properties": {"location_id": {"type": "integer", "description": "Unique identifier of the location."}, "name": {"type": "string", "description": "Name of the location."}, "active": {"type": "boolean", "description": "Whether the location is currently active."}, "plot_no": {"type": "string", "description": "Plot number of the location."}, "street": {"type": "string", "description": "Street address of the location."}, "city": {"type": "string", "description": "City where the location is situated."}, "country": {"type": "string", "description": "Country where the location is situated."}, "created_before": {"type": "string", "description": "Filter for locations created before this timestamp (ISO format)."}, "created_after": {"type": "string", "description": "Filter for locations created after this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "retrieve_installed_products", "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.", "parameters": {"type": "object", "properties": {"installed_product_id": {"type": "integer", "description": "Unique installed product ID."}, "location_id": {"type": "integer", "description": "Filter by location/site ID. Unique identifier which relates to the location table record."}, "account_id": {"type": "integer", "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "serial_number": {"type": "string", "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."}, "status": {"type": "string", "enum": ["in_use", "in_stock", "repair", "retired"], "description": "Current status of the installed product."}, "warranty_end": {"type": "string", "description": "Exact warranty end date (YYYY-MM-DD)."}, "created_before": {"type": "string", "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251210_002938_761_897c3e0b_f075229a", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "stephanie.todd@servicenow.com"}, "user_info": {"user_id": 6, "name": "Stephanie Todd", "email": "stephanie.todd@servicenow.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Case created with correct attributes", "description": "Verify case was created with account_id=52, product_id=133, installed_product_id=295, priority=moderate, channel=community, exact description, and assignment_group_id=10", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND assignment_group_id = 10;", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case linked to primary contact", "description": "Verify the case is associated with a primary contact (contact with is_primary=1) for account_id=52", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case cc JOIN contact c ON cc.contact_id = c.contact_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND c.is_primary = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case state updated to in_progress", "description": "Verify case state was changed to 'in_progress' (required by policy before SLA linking)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND state = 'in_progress' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Correct installed product linked (serial ends with 9300)", "description": "Verify the case is linked to installed_product_id=295 (Dell PowerEdge with serial ending in 9300 at Mumbai location)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case assigned to Installed Base Support group", "description": "Verify case was assigned to Installed Base Support (group_id=10) - the 'first foundation-level installed product support squad'", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Response SLA linked for moderate priority", "description": "Verify a response SLA for moderate priority was linked to the case (any moderate response SLA acceptable, since none with pause_on_pending=false exist)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id JOIN sla_definition sd ON cs.sla_def_id = sd.sla_def_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND sd.metric = 'response' AND sd.applies_to_priority = 'moderate' AND sd.active = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "SLA timer started (stage in_progress)", "description": "Verify the SLA was started with stage='in_progress' and start_time is set ('get that timer ticking')", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND cs.stage = 'in_progress' AND cs.start_time IS NOT NULL AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "No duplicate cases created", "description": "Verify exactly ONE case was created for this scenario (no duplicates)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Case sys_updated_on changed after state transition", "description": "Verify case sys_updated_on timestamp is later than sys_created_on (confirms state was updated after creation)", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND sys_updated_on > sys_created_on;", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["link_new_case_sla", "create_new_case", "retrieve_installed_products", "get_accounts", "find_account", "list_user_groups", "update_case", "find_locations", "find_contacts", "find_product_by_id", "find_sla_definitions"], "restricted_tools": [], "tool_to_gym": {"find_account": "sn-csm-server", "find_product_by_id": "sn-csm-server", "list_user_groups": "sn-csm-server", "get_accounts": "sn-csm-server", "find_contacts": "sn-csm-server", "find_locations": "sn-csm-server", "retrieve_installed_products": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server"}}}
+{"responses_create_params": {"input": [{"role": "system", "content": "CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided \u2192 default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new \u2192 in_progress, in_progress \u2192 pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new \u2192 in_progress / pending / resolved in_progress \u2192 pending / resolved pending \u2192 in_progress / resolved resolved \u2192 closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid \u2192 inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30\u2013120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities."}, {"role": "user", "content": "As part of a readiness check for a new business-critical service and the broader rollout, a few coordinated updates are required. First, confirm that Curtis Mccoy is active and ready to take on high-impact responsibilities along with his team for this rollout. Then register a new active service named \u201cNetwork Resilience Health Check\u201d, and create an internal troubleshooting guide titled \u201cNetwork Resilience Health Check Troubleshooting\u201d for it.\n\nWithdraw the incorrectly opened case CS-0000888 for Stark, Petersen and Palmer so it no longer affects workload reporting. Next, create a phone-reported support case for the same account related to operational instability tied to this service. Validate entitlement coverage,route the case using the handling method currently in place for this implementation, link the troubleshooting guide as a suggested reference, apply the critical-response SLA, and ensure the case is positioned for immediate technical action with proper priority due to the high business risk involved."}], "tools": [{"type": "function", "name": "find_user", "description": "Look up a user (portal customer, portal user or internal agent) by full name.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Full name of user, e.g., 'Harry Middleton'."}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "find_account", "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Exact account name, e.g., 'Wood and Sons'.", "minLength": 1}}, "required": ["name"]}, "strict": false}, {"type": "function", "name": "list_user_groups", "description": "List user groups with optional filters.", "parameters": {"type": "object", "properties": {"group_id": {"type": "integer", "description": "Filter by unique group identifier."}, "name": {"type": "string", "description": "Filter by group name (exact match, unique)."}, "active": {"type": "boolean", "description": "Filter by active status (true = active, false = inactive)."}, "type": {"type": "string", "enum": ["support", "backoffice", "field", "vendor"], "description": "Filter by group type (support, backoffice, field, vendor)."}, "created_after": {"type": "string", "description": "Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "list_group_members", "description": "List user group members with optional filters. Combination of group_id and user_id is unique.", "parameters": {"type": "object", "properties": {"member_id": {"type": "integer", "description": "Filter by unique membership identifier."}, "group_id": {"type": "integer", "description": "Filter by group identifier."}, "user_id": {"type": "integer", "description": "Filter by user identifier."}, "created_after": {"type": "string", "description": "Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "find_contacts", "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.", "parameters": {"type": "object", "properties": {"contact_id": {"type": "integer", "description": "Unique identifier of the contact."}, "account_id": {"type": "integer", "description": "ID of the account this contact belongs to."}, "portal_user_id": {"type": "integer", "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}, "active": {"type": "boolean", "description": "Whether the contact is currently active."}, "is_primary": {"type": "boolean", "description": "True if this is the primary contact for the account."}, "created_after": {"type": "string", "description": "Filter for contacts created after this timestamp (ISO format)."}, "created_before": {"type": "string", "description": "Filter for contacts created before this timestamp (ISO format)."}}}, "strict": false}, {"type": "function", "name": "find_entitlements", "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.", "parameters": {"type": "object", "properties": {"entitlement_id": {"type": "integer", "description": "Unique identifier of the entitlement."}, "account_id": {"type": "integer", "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."}, "product_id": {"type": "integer", "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."}, "contract_id": {"type": "integer", "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."}, "support_level": {"type": "string", "enum": ["standard", "premium", "enterprise"], "description": "Support level associated with the entitlement."}, "coverage_hours": {"type": "string", "enum": ["h8x5", "h12x6", "h24x7"], "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."}, "max_cases_per_month": {"type": "integer", "description": "Maximum number of support cases allowed per month under this entitlement."}, "active": {"type": "boolean", "description": "Filter by entitlement status (true = active, false = inactive)."}, "created_before": {"type": "string", "description": "Return entitlements created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return entitlements created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "integer", "description": "Unique identifier of the SLA definition."}, "name": {"type": "string", "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').", "minLength": 1}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."}, "target_mins": {"type": "integer", "description": "Target duration for the SLA in minutes."}, "pause_on_pending": {"type": "boolean", "description": "Whether the SLA timer pauses when the case is in a pending state."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level this SLA definition applies to."}, "active": {"type": "boolean", "description": "Whether the SLA definition is active (true) or inactive (false)."}, "created_before": {"type": "string", "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."}, "created_after": {"type": "string", "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."}}}, "strict": false}, {"type": "function", "name": "search_cases", "description": "Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case."}, "number": {"type": "string", "description": "Case number (unique human-readable reference)."}, "account_id": {"type": "integer", "description": "Filter by account ID. An account represents a business entity or organization."}, "contact_id": {"type": "integer", "description": "Filter by contact ID."}, "product_id": {"type": "integer", "description": "Filter by product ID. Unique identifier which relates to the product table record."}, "installed_product_id": {"type": "integer", "description": "Filter by installed product ID. Unique identifier which relates to the installed product table record."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was communicated/created."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "State of the case."}, "short_description": {"type": "string", "description": "Short description of the case."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation."}, "reopen_count": {"type": "integer", "description": "Filter by number of times the case was reopened."}, "closed_on": {"type": "string", "description": "Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."}, "created_before": {"type": "string", "description": "Return cases created before this date (YYYY-MM-DD HH:MM:SS)."}, "created_after": {"type": "string", "description": "Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}}, "strict": false}, {"type": "function", "name": "add_new_product", "description": "Create/register a product. Add product details. Products can be software, hardware, or services offered by the organization.", "parameters": {"type": "object", "properties": {"name": {"type": "string", "description": "Name of the product (e.g., 'Premium Support Package') (unique).", "minLength": 1}, "category": {"type": "string", "enum": ["software", "hardware", "service"], "description": "Product category (software, hardware, or service)."}, "lifecycle_state": {"type": "string", "enum": ["active", "retired"], "description": "Lifecycle state of the product (active or retired)."}, "product_price": {"type": "integer", "description": "Price of the product in the smallest currency unit (e.g., cents)."}}, "required": ["name", "category", "lifecycle_state"]}, "strict": false}, {"type": "function", "name": "create_new_case", "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"account_id": {"type": "integer", "description": "Account ID associated with the case."}, "contact_id": {"type": "integer", "description": "Contact ID who raised the case."}, "product_id": {"type": "integer", "description": "Product ID related to the case."}, "installed_product_id": {"type": "integer", "description": "Installed product ID associated with the case."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Channel through which the case was raised."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Priority level of the case."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Initial state of the case."}, "short_description": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Short description summarizing the case issue."}, "escalation": {"type": "boolean", "description": "Whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Reason for escalation if applicable.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Initial reopen count for the case."}, "closed_on": {"type": "string", "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Assignment group ID responsible for the case."}, "assigned_to": {"type": "integer", "description": "User ID assigned to the case."}}, "required": ["account_id", "contact_id", "channel", "priority", "state", "short_description"]}, "strict": false}, {"type": "function", "name": "update_case", "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case to update."}, "account_id": {"type": "integer", "description": "Update the associated account ID."}, "contact_id": {"type": "integer", "description": "Update the associated contact ID."}, "product_id": {"type": "integer", "description": "Update the product ID associated with the case."}, "installed_product_id": {"type": "integer", "description": "Update the installed product ID."}, "channel": {"type": "string", "enum": ["web", "email", "phone", "chat", "social", "alert", "community"], "description": "Update the channel used to create the case."}, "priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Update the case priority."}, "state": {"type": "string", "enum": ["new", "in_progress", "pending", "resolved", "closed", "canceled"], "description": "Update the case state."}, "short_description": {"type": "string", "description": "Update the case short description.", "minLength": 1, "maxLength": 500}, "escalation": {"type": "boolean", "description": "Update whether the case is escalated."}, "escalation_reason": {"type": "string", "enum": ["urgency", "vip", "impact", "breach_risk", "customer_request"], "description": "Update the escalation reason.", "minLength": 1}, "reopen_count": {"type": "integer", "description": "Update the reopen count."}, "closed_on": {"type": "string", "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."}, "assignment_group_id": {"type": "integer", "description": "Update the assignment group ID."}, "assigned_to": {"type": "integer", "description": "Update the assigned user ID."}}, "required": ["case_id"]}, "strict": false}, {"type": "function", "name": "link_new_case_sla", "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "ID of the case being linked to an SLA."}, "sla_def_id": {"type": "integer", "description": "ID of the SLA definition to apply."}, "stage": {"type": "string", "enum": ["in_progress", "paused", "completed", "canceled"], "description": "Initial stage of SLA tracking."}, "start_time": {"type": "string", "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."}, "breach_time": {"type": "string", "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."}, "has_breached": {"type": "boolean", "description": "Whether the SLA was already breached at creation (true/false)."}, "completed_time": {"type": "string", "description": "Completion timestamp if the SLA is already completed."}}, "required": ["case_id", "sla_def_id", "stage"]}, "strict": false}, {"type": "function", "name": "create_knowledge", "description": "Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.", "parameters": {"type": "object", "properties": {"title": {"type": "string", "description": "Title of the knowledge article.", "minLength": 1}, "state": {"type": "string", "enum": ["draft", "published", "retired"], "description": "Lifecycle state of the article."}, "body": {"type": "string", "description": "Body of the knowledge article."}, "visibility": {"type": "string", "enum": ["internal", "external"], "description": "Who can view the article: internal staff or external customers."}, "product_id": {"type": "integer", "description": "ID of the related product, if applicable."}, "owner_id": {"type": "integer", "description": "User ID of the article owner/author."}}, "required": ["title", "state", "body", "visibility", "owner_id"]}, "strict": false}, {"type": "function", "name": "link_case_knowledge", "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.", "parameters": {"type": "object", "properties": {"case_id": {"type": "integer", "description": "Unique identifier of the case being linked."}, "knowledge_id": {"type": "integer", "description": "Unique identifier of the knowledge article to link."}, "used_as": {"type": "string", "enum": ["suggested", "applied", "resolution"], "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}}, "required": ["case_id", "knowledge_id", "used_as"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251210_113549_827_d4a463c3_47b48a98", "domain": "csm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "sn-csm-server", "mcp_server_url": "http://localhost:8001", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql", "context": {"x-user-email": "jose.roberson@servicenow.com"}, "user_info": ""}], "verifiers": [{"verifier_type": "database_state", "name": "Verify New Product", "description": "Verify New Product", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS service_healthy_cnt\nFROM product AS p\nWHERE p.name = 'Network Resilience Health Check'\nAND p.category = 'service'\nAND p.lifecycle_state = 'active';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Update Case", "description": "Verify Update Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_888_canceled_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 888\nAND cc.state = 'canceled';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify Knowledge Created", "description": "Verify Knowledge Created", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS kb_network_resilience_cnt\nFROM knowledge AS k\nWHERE k.title = 'Network Resilience Health Check Troubleshooting'\nAND k.state = 'published'\nAND k.visibility = 'internal'\nAND k.owner_id = 32\nAND k.product_id = 241;\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case", "description": "Verify New Case", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_network_resilience_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 1233 \nAND cc.account_id = 38\nAND cc.contact_id = 84\nAND cc.product_id = 241\nAND cc.channel = 'phone'\nAND cc.priority = 'critical'\nAND cc.state = 'in_progress'\nAND cc.assignment_group_id = 18\nAND cc.escalation = 1\nAND cc.escalation_reason = 'impact';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case Knowledge Link", "description": "Verify New Case Knowledge Link", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_1233_kb_370_cnt\nFROM case_knowledge AS ck\nWHERE ck.case_id = 1233\nAND ck.knowledge_id = 370\nAND ck.used_as = 'suggested';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify New Case SLA", "description": "Verify New Case SLA", "gym_name": "sn-csm-server", "validation_config": {"query": "SELECT COUNT(*) AS case_1234_sla_cnt\nFROM case_sla AS cs\nWHERE cs.case_id = 1233\nAND cs.sla_def_id = 1\nAND cs.stage = 'in_progress';\n", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_sla_definitions", "find_account", "link_new_case_sla", "find_entitlements", "search_cases", "list_group_members", "create_new_case", "find_contacts", "update_case", "create_knowledge", "list_user_groups", "link_case_knowledge", "find_user", "add_new_product"], "restricted_tools": [], "tool_to_gym": {"find_user": "sn-csm-server", "find_account": "sn-csm-server", "list_user_groups": "sn-csm-server", "list_group_members": "sn-csm-server", "find_contacts": "sn-csm-server", "find_entitlements": "sn-csm-server", "find_sla_definitions": "sn-csm-server", "search_cases": "sn-csm-server", "add_new_product": "sn-csm-server", "create_new_case": "sn-csm-server", "update_case": "sn-csm-server", "link_new_case_sla": "sn-csm-server", "create_knowledge": "sn-csm-server", "link_case_knowledge": "sn-csm-server"}}}
diff --git a/resources_servers/enterpriseops_gym/data/example_metrics.json b/resources_servers/enterpriseops_gym/data/example_metrics.json
new file mode 100644
index 0000000000..f8bdd76579
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/example_metrics.json
@@ -0,0 +1,39 @@
+{
+ "name": "example",
+ "type": "example",
+ "jsonl_fpath": "resources_servers/enterpriseops_gym/data/example.jsonl",
+ "num_repeats": 1,
+ "source": null,
+ "gitlab_identifier": null,
+ "huggingface_identifier": null,
+ "license": null,
+ "Number of examples": 5,
+ "Number of tools": {
+ "Total # non-null values": 5,
+ "Average": 11.2,
+ "Min": 8.0,
+ "Max": 14.0,
+ "Standard deviation": 2.17
+ },
+ "Json-dumped number of words (proxy for token count)": {
+ "Total # non-null values": 5,
+ "Average": 3180.8,
+ "Min": 2765.0,
+ "Max": 3591.0,
+ "Standard deviation": 297.76
+ },
+ "Number of turns": {
+ "Total # non-null values": 5,
+ "Average": 1.0,
+ "Min": 1.0,
+ "Max": 1.0,
+ "Standard deviation": 0.0
+ },
+ "Temperature": {
+ "Total # non-null values": 0,
+ "Average": 0.0,
+ "Min": 0.0,
+ "Max": 0.0,
+ "Standard deviation": 0.0
+ }
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/example_rollouts.jsonl b/resources_servers/enterpriseops_gym/data/example_rollouts.jsonl
new file mode 100644
index 0000000000..18957b4b2b
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/example_rollouts.jsonl
@@ -0,0 +1,5 @@
+{"responses_create_params":{"background":null,"include":null,"input":[{"content":"CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided → default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new → in_progress, in_progress → pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new → in_progress / pending / resolved in_progress → pending / resolved pending → in_progress / resolved resolved → closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid → inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30–120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities.","role":"system","type":"message"},{"content":"The Wilson and Sons customer reached out via email, explaining that they had previously logged a case that was closed on 2nd October 2025 for their Managed Network Services asset but was eventually canceled. The issue is still ongoing, and they now want the case recreated and also mentioned that they want to escalate this since the problem has persisted for too long. Please open a case using the same contact, product, issue description, and priority from the canceled one, set the channel to email, assign it to the Case Assignment_2 team, and allocate it to agent Cory Vargas. Once the case is created, confirm that the entitlement is active and attach all SLAs appropriate for the priority level.","role":"user","type":"message"}],"instructions":null,"max_output_tokens":16384,"max_tool_calls":null,"metadata":null,"model":null,"parallel_tool_calls":true,"previous_response_id":null,"prompt":null,"reasoning":null,"service_tier":null,"store":null,"temperature":0.0,"text":null,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name."},{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business."},{"name":"find_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Product name, e.g., 'Pulse Edge'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Look up a product by its exact name. Product represents an item or service offered by the company."},{"name":"find_user_group","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact name of the user group (unique).","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes."},{"name":"check_user_membership","parameters":{"type":"object","properties":{"user_id":{"type":"integer","description":"User's unique id to check"},"group_id":{"type":"integer","description":"User group's unique id to check"}},"required":["user_id","group_id"]},"strict":false,"type":"function","description":"Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes."},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact."},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement."},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority."},{"name":"search_cases","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case."},"number":{"type":"string","description":"Case number (unique human-readable reference)."},"account_id":{"type":"integer","description":"Filter by account ID. An account represents a business entity or organization."},"contact_id":{"type":"integer","description":"Filter by contact ID."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"installed_product_id":{"type":"integer","description":"Filter by installed product ID. Unique identifier which relates to the installed product table record."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was communicated/created."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"State of the case."},"short_description":{"type":"string","description":"Short description of the case."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation."},"reopen_count":{"type":"integer","description":"Filter by number of times the case was reopened."},"closed_on":{"type":"string","description":"Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return cases created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution."},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case."}],"top_logprobs":null,"top_p":null,"truncation":null,"user":null,"stream":null},"response":{"id":"resp_kjLo-_MQTahcRH9KPPDo6_IhfEn8JaRdIIjXGf5P2OTXxFGpBPTSDXJ1XjLKgN1czWl7r2_pKVlcs6pCvZaCrr_eh8F2kRD4Jso-D66_4ooGtWLxDvaOgbea1s2Z88T7uHNNUUXCs0y_MW-wMedMSII-2SdHh5znYgJGJBR0KT7JjhPF_DiSWpUBi4Zjx7_RD37tge748Myc7lYKQyYJtYRJpCR6DDY-fbQLYRoB35cs6Eg70aB0NKcL40JmuOahYkq8VDkPfkTuDASU-8qj_CbbZeOT1v-SZNNZJGd4Pm9oo_3XWPk9f03-lGAp-GsMWSovgl6i_t5Cv6_VE2e25p6ef1KvFxmFy-kS01-ERdPgS40YFRY_A7jovqARRhjUvLJ-gcQA2JGvRi7m8IE=","created_at":1784935523.0,"error":null,"incomplete_details":null,"instructions":null,"metadata":{},"model":"azure/openai/gpt-4.1-mini","object":"response","output":[{"arguments":"{\"name\":\"The Wilson and Sons\"}","call_id":"call_ga9lyWUtPqJicyzg00gqdVU9","name":"find_account","type":"function_call","id":"fc_05fcd2a04d708060006a63f46209a88195b1b3f0ebbe5843ab","status":"completed"},{"call_id":"call_ga9lyWUtPqJicyzg00gqdVU9","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"Error: x-database-id header is required for database isolation\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"id":"msg_05fcd2a04d708060006a63f463b82c8195bfcdf0625f7eef8d","content":[{"annotations":[],"text":"I am currently unable to access the account information for \"The Wilson and Sons\" due to a system error related to database isolation. This prevents me from proceeding with recreating the case and performing the required actions. Please try again later or provide an alternative request.","type":"output_text","logprobs":[]}],"role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"temperature":0.0,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name.","defer_loading":null},{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.","defer_loading":null},{"name":"find_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Product name, e.g., 'Pulse Edge'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Look up a product by its exact name. Product represents an item or service offered by the company.","defer_loading":null},{"name":"find_user_group","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact name of the user group (unique).","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.","defer_loading":null},{"name":"check_user_membership","parameters":{"type":"object","properties":{"user_id":{"type":"integer","description":"User's unique id to check"},"group_id":{"type":"integer","description":"User group's unique id to check"}},"required":["user_id","group_id"]},"strict":false,"type":"function","description":"Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes.","defer_loading":null},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.","defer_loading":null},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.","defer_loading":null},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.","defer_loading":null},{"name":"search_cases","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case."},"number":{"type":"string","description":"Case number (unique human-readable reference)."},"account_id":{"type":"integer","description":"Filter by account ID. An account represents a business entity or organization."},"contact_id":{"type":"integer","description":"Filter by contact ID."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"installed_product_id":{"type":"integer","description":"Filter by installed product ID. Unique identifier which relates to the installed product table record."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was communicated/created."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"State of the case."},"short_description":{"type":"string","description":"Short description of the case."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation."},"reopen_count":{"type":"integer","description":"Filter by number of times the case was reopened."},"closed_on":{"type":"string","description":"Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return cases created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.","defer_loading":null},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.","defer_loading":null}],"top_p":1.0,"background":false,"conversation":null,"max_output_tokens":16384,"max_tool_calls":null,"previous_response_id":null,"prompt":null,"prompt_cache_key":null,"reasoning":{"effort":null,"generate_summary":null,"summary":null,"context":null},"safety_identifier":null,"service_tier":"default","status":"completed","text":{"format":{"type":"text"},"verbosity":"medium"},"top_logprobs":0,"truncation":"disabled","usage":{"input_tokens":9095,"input_tokens_details":{"cached_tokens":0,"audio_tokens":null,"text_tokens":null},"output_tokens":72,"output_tokens_details":{"reasoning_tokens":0,"text_tokens":null},"total_tokens":9167,"cost":null},"user":null,"store":true,"completed_at":1784935524,"content_filters":[{"blocked":false,"source_type":"completion","content_filter_raw":[],"content_filter_results":{"protected_material_code":{"detected":false,"filtered":false},"protected_material_text":{"detected":false,"filtered":false},"hate":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"start_offset":0,"end_offset":287,"check_offset":0}}],"frequency_penalty":0.0,"moderation":null,"presence_penalty":0.0,"prompt_cache_retention":"in_memory"},"reward":0.0,"overall_success":false,"verifier_pass_rate":0.0,"verification_results":{"Verify case creation":{"passed":false,"error":"SQL query failed: Cannot serialize non-str key None","query":"SELECT COUNT(*) AS count FROM customer_case WHERE case_id = 1233 AND state = 'in_progress' AND assignment_group_id = 24 AND assigned_to = 427 AND channel = 'email' AND priority = 'critical' AND escalation_reason = 'customer_request' AND escalation = 1;"},"Verify group membership":{"passed":false,"error":"SQL query failed: Cannot serialize non-str key None","query":"SELECT COUNT(*) AS count FROM user_group_member WHERE group_id = 24 AND user_id = 427;"},"Verify case sla 1":{"passed":false,"error":"SQL query failed: Cannot serialize non-str key None","query":"SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 1;"},"Verify case sla 2":{"passed":false,"error":"SQL query failed: Cannot serialize non-str key None","query":"SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 6;"}},"strict_success":false,"strict_pass_rate":0.0,"num_verifiers_defined":4,"num_verifiers_scored":4,"num_tool_calls":1,"tool_latencies_ms":[{"tool":"find_account","gym":"sn-csm-server","latency_ms":3.2}],"verifier_metadata":{"task_id":"task_20251209_132736_542_99ba2325_6705caf4","domain":"csm","mode":"oracle","gym_servers_config":[{"mcp_server_name":"sn-csm-server","mcp_server_url":"http://localhost:8001","seed_database_file":"Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1765219280033_d7pqrz32b.sql","context":{"x-user-email":"jose.roberson@servicenow.com"},"user_info":{"user_id":32,"name":"Jose Roberson","email":"jose.roberson@servicenow.com"}}],"verifiers":[{"verifier_type":"database_state","name":"Verify case creation","description":"Verify case creation","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS count FROM customer_case WHERE case_id = 1233 AND state = 'in_progress' AND assignment_group_id = 24 AND assigned_to = 427 AND channel = 'email' AND priority = 'critical' AND escalation_reason = 'customer_request' AND escalation = 1;","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify group membership","description":"Verify group membership","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS count FROM user_group_member WHERE group_id = 24 AND user_id = 427;","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify case sla 1","description":"Verify case sla 1","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 1;","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify case sla 2","description":"Verify case sla 2","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS count FROM case_sla WHERE case_id = 1233 AND stage = 'in_progress' AND sla_def_id = 6;","expected_value":1,"comparison_type":"equals"}}],"selected_tools":["find_user_group","update_case","find_user","find_entitlements","find_contacts","link_new_case_sla","find_sla_definitions","search_cases","check_user_membership","find_product","find_account","create_new_case"],"restricted_tools":[],"tool_to_gym":{"find_user":"sn-csm-server","find_account":"sn-csm-server","find_product":"sn-csm-server","find_user_group":"sn-csm-server","check_user_membership":"sn-csm-server","find_contacts":"sn-csm-server","find_entitlements":"sn-csm-server","find_sla_definitions":"sn-csm-server","search_cases":"sn-csm-server","create_new_case":"sn-csm-server","update_case":"sn-csm-server","link_new_case_sla":"sn-csm-server"}},"agent_ref":{"name":"enterpriseops_gym_simple_agent"},"_ng_task_index":2,"_ng_rollout_index":0}
+{"responses_create_params":{"background":null,"include":null,"input":[{"content":"CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided → default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new → in_progress, in_progress → pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new → in_progress / pending / resolved in_progress → pending / resolved pending → in_progress / resolved resolved → closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid → inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30–120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities.","role":"system","type":"message"},{"content":"Klein Black and Wood's India facility reported via community post that their Dell rack server keeps hitting kernel panics. I forgot to note the machine's serial, but I remember it wraps up with the digits 9300. Log this at mid-range priority through the community channel using their lead site contact. Pass it to the first foundation-level installed product support squad. Bind a response timer appropriate for that priority bracket. If possible, pick one that doesn't freeze during customer wait states. Get that timer ticking, but the case should show initial registration status, not active work if it's possible. The description must read 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' exactly as written.","role":"user","type":"message"}],"instructions":null,"max_output_tokens":16384,"max_tool_calls":null,"metadata":null,"model":null,"parallel_tool_calls":true,"previous_response_id":null,"prompt":null,"reasoning":null,"service_tier":null,"store":null,"temperature":0.0,"text":null,"tool_choice":"auto","tools":[{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business."},{"name":"find_product_by_id","parameters":{"type":"object","properties":{"product_id":{"type":"integer","description":" Unique identifier of the product."}},"required":["product_id"]},"strict":false,"type":"function","description":"Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id."},{"name":"list_user_groups","parameters":{"type":"object","properties":{"group_id":{"type":"integer","description":"Filter by unique group identifier."},"name":{"type":"string","description":"Filter by group name (exact match, unique)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"type":{"type":"string","enum":["support","backoffice","field","vendor"],"description":"Filter by group type (support, backoffice, field, vendor)."},"created_after":{"type":"string","description":"Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user groups with optional filters."},{"name":"get_accounts","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Filter by unique account identifier."},"name":{"type":"string","description":"Filter by account name (e.g., 'Acme Systems') (unique). Name of the company/organization associated with the account.","minLength":1},"email_domain":{"type":"string","description":"Filter by account email domain (e.g., 'acme.com'). it is the domain part of email addresses associated with the account or the website.","minLength":1},"account_types":{"type":"array","items":{"type":"string","enum":["customer","partner","internal"]},"description":"Filter by one or more account types (customer, partner, internal)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"created_after":{"type":"string","description":"Return only accounts created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only accounts created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List accounts with optional filters. All the inputs are optional, not providing any filter will return all accounts. Account represents a business entity or organization."},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact."},{"name":"find_locations","parameters":{"type":"object","properties":{"location_id":{"type":"integer","description":"Unique identifier of the location."},"name":{"type":"string","description":"Name of the location."},"active":{"type":"boolean","description":"Whether the location is currently active."},"plot_no":{"type":"string","description":"Plot number of the location."},"street":{"type":"string","description":"Street address of the location."},"city":{"type":"string","description":"City where the location is situated."},"country":{"type":"string","description":"Country where the location is situated."},"created_before":{"type":"string","description":"Filter for locations created before this timestamp (ISO format)."},"created_after":{"type":"string","description":"Filter for locations created after this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides."},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts."},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority."},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case."}],"top_logprobs":null,"top_p":null,"truncation":null,"user":null,"stream":null},"response":{"id":"resp_uI033dpBpNV5ydrCRGPJQGLjoLksF8LgrW0eDahhvOYLaUPhemVSjAiqsOF3Se_kNGQqnGU1g7iF9VqTy9keLlF5b_mZ2l_7s5zQNS1OxdscD03BtG1QmYGQQYj17skORkact5CIxX2kAxt8lLajB-ZJYs4yx7jU8lnjpL5bC35jL7D9oFAHlb9OrG4_S6AIl7bXxDjChKmr0SHShmiiI97x9CwWJxwBenOOKv7kM8NEDJX4rxqvJ4rGumSI8tDwX7VHhkH_WrcY9viKypzWETHIix-aUvE9SaHJsq5C8hz0Xs7-cXfnY94oo9T6LFJdw_V-qZnbmA6g1TAZKdlALXN0SmdM9nge4skwWg2VmI16lJkDUDNmopAtG8xrMCC3aqUEzQPfFXqb2J8kh9o=","created_at":1784935525.0,"error":null,"incomplete_details":null,"instructions":null,"metadata":{},"model":"azure/openai/gpt-4.1-mini","object":"response","output":[{"arguments":"{\"name\":\"Klein Black and Wood\"}","call_id":"call_xIxU0yyTVRhheUOBJZKbghAH","name":"find_account","type":"function_call","id":"fc_0b844b9de65a15b6006a63f462f7488196a7711f14b353c7bd","status":"completed"},{"arguments":"{\"name\":\"foundation-level installed product support squad\",\"active\":true,\"type\":\"support\"}","call_id":"call_RBycJvEPqZjOICFo3ZrNuiCV","name":"list_user_groups","type":"function_call","id":"fc_0b844b9de65a15b6006a63f462f75c8196893bbf42da157c41","status":"completed"},{"call_id":"call_xIxU0yyTVRhheUOBJZKbghAH","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_RBycJvEPqZjOICFo3ZrNuiCV","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"name\":\"Klein Black and Wood\"}","call_id":"call_Y3SQqpLVtd3hRNt2S5c7AxbU","name":"get_accounts","type":"function_call","id":"fc_0b844b9de65a15b6006a63f46483c08196a6459fb85281fff3","status":"completed"},{"call_id":"call_Y3SQqpLVtd3hRNt2S5c7AxbU","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"id":"msg_0b844b9de65a15b6006a63f4660124819689eaa96931ef76c1","content":[{"annotations":[],"text":"I could not find the account \"Klein Black and Wood\" in the system. Could you please verify the account name or provide any other details to help locate the account?","type":"output_text","logprobs":[]}],"role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"temperature":0.0,"tool_choice":"auto","tools":[{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.","defer_loading":null},{"name":"find_product_by_id","parameters":{"type":"object","properties":{"product_id":{"type":"integer","description":" Unique identifier of the product."}},"required":["product_id"]},"strict":false,"type":"function","description":"Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id.","defer_loading":null},{"name":"list_user_groups","parameters":{"type":"object","properties":{"group_id":{"type":"integer","description":"Filter by unique group identifier."},"name":{"type":"string","description":"Filter by group name (exact match, unique)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"type":{"type":"string","enum":["support","backoffice","field","vendor"],"description":"Filter by group type (support, backoffice, field, vendor)."},"created_after":{"type":"string","description":"Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user groups with optional filters.","defer_loading":null},{"name":"get_accounts","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Filter by unique account identifier."},"name":{"type":"string","description":"Filter by account name (e.g., 'Acme Systems') (unique). Name of the company/organization associated with the account.","minLength":1},"email_domain":{"type":"string","description":"Filter by account email domain (e.g., 'acme.com'). it is the domain part of email addresses associated with the account or the website.","minLength":1},"account_types":{"type":"array","items":{"type":"string","enum":["customer","partner","internal"]},"description":"Filter by one or more account types (customer, partner, internal)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"created_after":{"type":"string","description":"Return only accounts created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only accounts created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List accounts with optional filters. All the inputs are optional, not providing any filter will return all accounts. Account represents a business entity or organization.","defer_loading":null},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.","defer_loading":null},{"name":"find_locations","parameters":{"type":"object","properties":{"location_id":{"type":"integer","description":"Unique identifier of the location."},"name":{"type":"string","description":"Name of the location."},"active":{"type":"boolean","description":"Whether the location is currently active."},"plot_no":{"type":"string","description":"Plot number of the location."},"street":{"type":"string","description":"Street address of the location."},"city":{"type":"string","description":"City where the location is situated."},"country":{"type":"string","description":"Country where the location is situated."},"created_before":{"type":"string","description":"Filter for locations created before this timestamp (ISO format)."},"created_after":{"type":"string","description":"Filter for locations created after this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.","defer_loading":null},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.","defer_loading":null},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.","defer_loading":null},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.","defer_loading":null}],"top_p":1.0,"background":false,"conversation":null,"max_output_tokens":16384,"max_tool_calls":null,"previous_response_id":null,"prompt":null,"prompt_cache_key":null,"reasoning":{"effort":null,"generate_summary":null,"summary":null,"context":null},"safety_identifier":null,"service_tier":"default","status":"completed","text":{"format":{"type":"text"},"verbosity":"medium"},"top_logprobs":0,"truncation":"disabled","usage":{"input_tokens":13766,"input_tokens_details":{"cached_tokens":0,"audio_tokens":null,"text_tokens":null},"output_tokens":119,"output_tokens_details":{"reasoning_tokens":0,"text_tokens":null},"total_tokens":13885,"cost":null},"user":null,"store":true,"completed_at":1784935526,"content_filters":[{"blocked":false,"source_type":"completion","content_filter_raw":[],"content_filter_results":{"protected_material_code":{"detected":false,"filtered":false},"protected_material_text":{"detected":false,"filtered":false},"hate":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"start_offset":0,"end_offset":164,"check_offset":0}}],"frequency_penalty":0.0,"moderation":null,"presence_penalty":0.0,"prompt_cache_retention":"in_memory"},"reward":0.0,"overall_success":false,"verifier_pass_rate":0.1111111111111111,"verification_results":{"Case created with correct attributes":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND assignment_group_id = 10;","details":"Comparison equals: 0 vs 1"},"Case linked to primary contact":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case cc JOIN contact c ON cc.contact_id = c.contact_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND c.is_primary = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"Case state updated to in_progress":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND state = 'in_progress' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"Correct installed product linked (serial ends with 9300)":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"Case assigned to Installed Base Support group":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"Response SLA linked for moderate priority":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id JOIN sla_definition sd ON cs.sla_def_id = sd.sla_def_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND sd.metric = 'response' AND sd.applies_to_priority = 'moderate' AND sd.active = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"SLA timer started (stage in_progress)":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND cs.stage = 'in_progress' AND cs.start_time IS NOT NULL AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"No duplicate cases created":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","details":"Comparison equals: 0 vs 1"},"Case sys_updated_on changed after state transition":{"passed":true,"expected":1,"actual":1,"comparison_type":"equals","query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND sys_updated_on > sys_created_on;","details":"Comparison equals: 1 vs 1"}},"strict_success":false,"strict_pass_rate":0.1111111111111111,"num_verifiers_defined":9,"num_verifiers_scored":9,"num_tool_calls":3,"tool_latencies_ms":[{"tool":"find_account","gym":"sn-csm-server","latency_ms":10.5},{"tool":"list_user_groups","gym":"sn-csm-server","latency_ms":8.6},{"tool":"get_accounts","gym":"sn-csm-server","latency_ms":11.5}],"verifier_metadata":{"task_id":"task_20251210_002938_761_897c3e0b_f075229a","domain":"csm","mode":"oracle","gym_servers_config":[{"mcp_server_name":"sn-csm-server","mcp_server_url":"http://localhost:8001","seed_database_file":"Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql","context":{"x-user-email":"stephanie.todd@servicenow.com"},"user_info":{"user_id":6,"name":"Stephanie Todd","email":"stephanie.todd@servicenow.com"}}],"verifiers":[{"verifier_type":"database_state","name":"Case created with correct attributes","description":"Verify case was created with account_id=52, product_id=133, installed_product_id=295, priority=moderate, channel=community, exact description, and assignment_group_id=10","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND assignment_group_id = 10;","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Case linked to primary contact","description":"Verify the case is associated with a primary contact (contact with is_primary=1) for account_id=52","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case cc JOIN contact c ON cc.contact_id = c.contact_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND c.is_primary = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Case state updated to in_progress","description":"Verify case state was changed to 'in_progress' (required by policy before SLA linking)","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND state = 'in_progress' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Correct installed product linked (serial ends with 9300)","description":"Verify the case is linked to installed_product_id=295 (Dell PowerEdge with serial ending in 9300 at Mumbai location)","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND installed_product_id = 295 AND priority = 'moderate' AND channel = 'community' AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Case assigned to Installed Base Support group","description":"Verify case was assigned to Installed Base Support (group_id=10) - the 'first foundation-level installed product support squad'","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND assignment_group_id = 10 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Response SLA linked for moderate priority","description":"Verify a response SLA for moderate priority was linked to the case (any moderate response SLA acceptable, since none with pause_on_pending=false exist)","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id JOIN sla_definition sd ON cs.sla_def_id = sd.sla_def_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND sd.metric = 'response' AND sd.applies_to_priority = 'moderate' AND sd.active = 1 AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"SLA timer started (stage in_progress)","description":"Verify the SLA was started with stage='in_progress' and start_time is set ('get that timer ticking')","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM case_sla cs JOIN customer_case cc ON cs.case_id = cc.case_id WHERE cc.account_id = 52 AND cc.product_id = 133 AND cs.stage = 'in_progress' AND cs.start_time IS NOT NULL AND cc.short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"No duplicate cases created","description":"Verify exactly ONE case was created for this scenario (no duplicates)","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND priority = 'moderate' AND channel = 'community' AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.';","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Case sys_updated_on changed after state transition","description":"Verify case sys_updated_on timestamp is later than sys_created_on (confirms state was updated after creation)","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM customer_case WHERE account_id = 52 AND product_id = 133 AND short_description = 'Product: Dell PowerEdge R740 (Config 1), Issue: is not working as expected.' AND sys_updated_on > sys_created_on;","expected_value":1,"comparison_type":"equals"}}],"selected_tools":["link_new_case_sla","create_new_case","retrieve_installed_products","get_accounts","find_account","list_user_groups","update_case","find_locations","find_contacts","find_product_by_id","find_sla_definitions"],"restricted_tools":[],"tool_to_gym":{"find_account":"sn-csm-server","find_product_by_id":"sn-csm-server","list_user_groups":"sn-csm-server","get_accounts":"sn-csm-server","find_contacts":"sn-csm-server","find_locations":"sn-csm-server","retrieve_installed_products":"sn-csm-server","find_sla_definitions":"sn-csm-server","create_new_case":"sn-csm-server","update_case":"sn-csm-server","link_new_case_sla":"sn-csm-server"}},"agent_ref":{"name":"enterpriseops_gym_simple_agent"},"_ng_task_index":3,"_ng_rollout_index":0}
+{"responses_create_params":{"background":null,"include":null,"input":[{"content":"CSM Agent Policy\n\nYou are a Customer Service Management assistant. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, ing record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account’s data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided → default = moderate) Default state = new. Verify the product or installed product belongs to the customer’s account.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group. Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new → in_progress, in_progress → pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new → in_progress / pending / resolved in_progress → pending / resolved pending → in_progress / resolved resolved → closed / new canceled At each step: Validate acting user’s relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid → inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product’s product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer’s entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30–120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities.","role":"system","type":"message"},{"content":"During our December 5th, 2025 review of the London setup, we noticed that the facility with the older plot and curve address pattern in the 90s area is being reorganized. One of the P25-serial type devices at that location needs its records updated, and the device's warranty window is coming up soon.\nPlease update the system by relocating this device to the London site with the newer plot and street configuration, specifically the one on the Pratt Curve side, and ensure its status remains operational. After completing the update, please send a notification to the associated account contacts for this product so they're aware of the change.","role":"user","type":"message"}],"instructions":null,"max_output_tokens":16384,"max_tool_calls":null,"metadata":null,"model":null,"parallel_tool_calls":true,"previous_response_id":null,"prompt":null,"reasoning":null,"service_tier":null,"store":null,"temperature":0.0,"text":null,"tool_choice":"auto","tools":[{"name":"list_users","parameters":{"type":"object","properties":{"email":{"type":"string","description":"Filter by user email address (exact match) (unique)."},"user_id":{"type":"integer","description":"Filter by unique user identifier."},"first_name":{"type":"string","description":"Filter by user's first name."},"last_name":{"type":"string","description":"Filter by user's last name."},"phone":{"type":"string","description":"Filter by phone number."},"role":{"type":"string","enum":["admin","agent","manager","customer"],"description":"Filter by user role (admin, agent, manager, or customer)."},"location_id":{"type":"integer","description":"Filter by location identifier."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"created_after":{"type":"string","description":"Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned."},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact."},{"name":"find_locations","parameters":{"type":"object","properties":{"location_id":{"type":"integer","description":"Unique identifier of the location."},"name":{"type":"string","description":"Name of the location."},"active":{"type":"boolean","description":"Whether the location is currently active."},"plot_no":{"type":"string","description":"Plot number of the location."},"street":{"type":"string","description":"Street address of the location."},"city":{"type":"string","description":"City where the location is situated."},"country":{"type":"string","description":"Country where the location is situated."},"created_before":{"type":"string","description":"Filter for locations created before this timestamp (ISO format)."},"created_after":{"type":"string","description":"Filter for locations created after this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides."},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts."},{"name":"update_installed_product_details","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID (required)."},"location_id":{"type":"integer","description":"Location/site ID where the product is installed."},"account_id":{"type":"integer","description":"Owning account ID for this installed product."},"product_id":{"type":"integer","description":"Product ID that was installed."},"serial_number":{"type":"string","description":"Unique serial number of the installed product.","minLength":1},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Status of the installed product."},"warranty_end":{"type":"string","description":"Warranty end date (YYYY-MM-DD)."}},"required":["installed_product_id"]},"strict":false,"type":"function","description":"Update an installed product (partial updates allowed). Combination of Account ID, Product ID, Serial Number should be unique."},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"send_notification","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Case ID this notification is related to."},"knowledge_id":{"type":"integer","description":"Optional knowledge article ID linked to this notification."},"email":{"type":"string","description":"Recipient email address of the notification.","minLength":1},"type":{"type":"string","enum":["report","update","alert","reminder","solution_proposal","next_steps","other"],"description":"Type of notification being sent."}},"required":["case_id","email","type"]},"strict":false,"type":"function","description":"Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case."}],"top_logprobs":null,"top_p":null,"truncation":null,"user":null,"stream":null},"response":{"id":"resp_uu4_0S9cVqSkPSFE5e8xvN_mQ8knuolIIuyU8WA7G9UtY6YrOWyBw4ZGAH1tE3OHKtyd69IZsqfLOmUTpJvzVuVDUPkVzqFpHjCrm6OFzPUahqXFvs3nImcxsjOeRyo0F8holPKDSXQ00ePhcxbTGe2jJwC7h9I5Hxk725boTUK3XmU0pqj6IPgT2izrIxBB_3VjOn02z4iwtChGmnYpEiO9d78KSgbGjKXwLzMqYA8cY7VwCNMfjIJHpiShR1Zf1O53mgDX7mir1h1Zkh6IOyd8Dz8mvetHbYTyuEb8s38x4K7EM49FGS5C8YLC_8X9b6CC5g3iobD1YARy8dAOETEpngjRagfj51PALrYjwitHofj4xR8dpaujH6-o0brcRO3PvcQOyN6Bu2KG_yU=","created_at":1784935540.0,"error":null,"incomplete_details":null,"instructions":null,"metadata":{},"model":"azure/openai/gpt-4.1-mini","object":"response","output":[{"arguments":"{\"city\":\"london\"}","call_id":"call_J8oelU6z7LwITbbx6PtWpP3Z","name":"find_locations","type":"function_call","id":"fc_031533b1546483e4006a63f462730881959cf9f61fe0ee813c","status":"completed"},{"call_id":"call_J8oelU6z7LwITbbx6PtWpP3Z","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"location_id\\\": 2, \\\"name\\\": \\\"User 2 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:01\\\"}, {\\\"location_id\\\": 7, \\\"name\\\": \\\"User 7 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:23\\\"}, {\\\"location_id\\\": 12, \\\"name\\\": \\\"User 12 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:17\\\"}, {\\\"location_id\\\": 17, \\\"name\\\": \\\"User 17 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Robert Harbors\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:33\\\"}, {\\\"location_id\\\": 22, \\\"name\\\": \\\"User 22 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Donald Drives\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:05\\\"}, {\\\"location_id\\\": 27, \\\"name\\\": \\\"User 27 - London\\\", \\\"plot_no\\\": \\\"Plot 551\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:07\\\"}, {\\\"location_id\\\": 32, \\\"name\\\": \\\"User 32 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Stewart Avenue\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:00\\\"}, {\\\"location_id\\\": 37, \\\"name\\\": \\\"User 37 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:32\\\"}, {\\\"location_id\\\": 42, \\\"name\\\": \\\"User 42 - London\\\", \\\"plot_no\\\": \\\"Plot 264\\\", \\\"street\\\": \\\"Michelle Glens\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:52\\\"}, {\\\"location_id\\\": 47, \\\"name\\\": \\\"User 47 - London\\\", \\\"plot_no\\\": \\\"Plot 995\\\", \\\"street\\\": \\\"Leah Springs\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:49\\\"}, {\\\"location_id\\\": 52, \\\"name\\\": \\\"User 52 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Williams Keys\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:30\\\"}, {\\\"location_id\\\": 57, \\\"name\\\": \\\"User 57 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:34\\\"}, {\\\"location_id\\\": 62, \\\"name\\\": \\\"User 62 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Howell Knoll\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:58\\\"}, {\\\"location_id\\\": 67, \\\"name\\\": \\\"User 67 - London\\\", \\\"plot_no\\\": \\\"Plot 753\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:06\\\"}, {\\\"location_id\\\": 72, \\\"name\\\": \\\"User 72 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Smith Park\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:40\\\"}, {\\\"location_id\\\": 77, \\\"name\\\": \\\"User 77 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Michael Manor\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:41\\\"}, {\\\"location_id\\\": 82, \\\"name\\\": \\\"User 82 - London\\\", \\\"plot_no\\\": \\\"Plot 102\\\", \\\"street\\\": \\\"Gregory Course\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:51\\\"}, {\\\"location_id\\\": 87, \\\"name\\\": \\\"User 87 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:12\\\"}, {\\\"location_id\\\": 92, \\\"name\\\": \\\"User 92 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:23\\\"}, {\\\"location_id\\\": 97, \\\"name\\\": \\\"User 97 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:42\\\"}, {\\\"location_id\\\": 102, \\\"name\\\": \\\"User 102 - London\\\", \\\"plot_no\\\": \\\"Plot 995\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:02\\\"}, {\\\"location_id\\\": 107, \\\"name\\\": \\\"User 107 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Rebecca Avenue\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:12\\\"}, {\\\"location_id\\\": 112, \\\"name\\\": \\\"User 112 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:55\\\"}, {\\\"location_id\\\": 117, \\\"name\\\": \\\"User 117 - London\\\", \\\"plot_no\\\": \\\"Plot 678\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:19\\\"}, {\\\"location_id\\\": 122, \\\"name\\\": \\\"User 122 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:00\\\"}, {\\\"location_id\\\": 127, \\\"name\\\": \\\"User 127 - London\\\", \\\"plot_no\\\": \\\"Plot 577\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:53\\\"}, {\\\"location_id\\\": 132, \\\"name\\\": \\\"User 132 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:13\\\"}, {\\\"location_id\\\": 137, \\\"name\\\": \\\"User 137 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Clark Estate\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:01\\\"}, {\\\"location_id\\\": 142, \\\"name\\\": \\\"User 142 - London\\\", \\\"plot_no\\\": \\\"Plot 378\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:34\\\"}, {\\\"location_id\\\": 147, \\\"name\\\": \\\"User 147 - London\\\", \\\"plot_no\\\": \\\"Plot 192\\\", \\\"street\\\": \\\"Newton Corners\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:56\\\"}, {\\\"location_id\\\": 152, \\\"name\\\": \\\"User 152 - London\\\", \\\"plot_no\\\": \\\"Plot 941\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:56\\\"}, {\\\"location_id\\\": 157, \\\"name\\\": \\\"User 157 - London\\\", \\\"plot_no\\\": \\\"Plot 61\\\", \\\"street\\\": \\\"Anthony Plains\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:20\\\"}, {\\\"location_id\\\": 162, \\\"name\\\": \\\"User 162 - London\\\", \\\"plot_no\\\": \\\"Plot 62\\\", \\\"street\\\": \\\"Hayes Gardens\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:46\\\"}, {\\\"location_id\\\": 167, \\\"name\\\": \\\"User 167 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"King Rapid\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:25\\\"}, {\\\"location_id\\\": 172, \\\"name\\\": \\\"User 172 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Jordan Forks\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:29\\\"}, {\\\"location_id\\\": 177, \\\"name\\\": \\\"User 177 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:05\\\"}, {\\\"location_id\\\": 182, \\\"name\\\": \\\"User 182 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:17\\\"}, {\\\"location_id\\\": 187, \\\"name\\\": \\\"User 187 - London\\\", \\\"plot_no\\\": \\\"Plot 952\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:38\\\"}, {\\\"location_id\\\": 192, \\\"name\\\": \\\"User 192 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Gabriella Glen\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:32\\\"}, {\\\"location_id\\\": 197, \\\"name\\\": \\\"User 197 - London\\\", \\\"plot_no\\\": \\\"Plot 664\\\", \\\"street\\\": \\\"Joshua Common\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:05\\\"}, {\\\"location_id\\\": 202, \\\"name\\\": \\\"User 202 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Mark Plaza\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:18\\\"}, {\\\"location_id\\\": 207, \\\"name\\\": \\\"User 207 - London\\\", \\\"plot_no\\\": \\\"Plot 786\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:58\\\"}, {\\\"location_id\\\": 212, \\\"name\\\": \\\"User 212 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Morrison Mountains\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:37\\\"}, {\\\"location_id\\\": 217, \\\"name\\\": \\\"User 217 - London\\\", \\\"plot_no\\\": \\\"Plot 484\\\", \\\"street\\\": \\\"Walsh Avenue\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:32\\\"}, {\\\"location_id\\\": 222, \\\"name\\\": \\\"User 222 - London\\\", \\\"plot_no\\\": \\\"Plot 717\\\", \\\"street\\\": \\\"Nicole Track\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:25\\\"}, {\\\"location_id\\\": 227, \\\"name\\\": \\\"User 227 - London\\\", \\\"plot_no\\\": \\\"Plot 271\\\", \\\"street\\\": \\\"Oscar Station\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:20\\\"}, {\\\"location_id\\\": 232, \\\"name\\\": \\\"User 232 - London\\\", \\\"plot_no\\\": \\\"Plot 938\\\", \\\"street\\\": \\\"Lori Haven\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:55\\\"}, {\\\"location_id\\\": 237, \\\"name\\\": \\\"User 237 - London\\\", \\\"plot_no\\\": \\\"Plot 713\\\", \\\"street\\\": \\\"Gregg Prairie\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:16\\\"}, {\\\"location_id\\\": 242, \\\"name\\\": \\\"User 242 - London\\\", \\\"plot_no\\\": \\\"Plot 903\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:09\\\"}, {\\\"location_id\\\": 247, \\\"name\\\": \\\"User 247 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:39\\\"}, {\\\"location_id\\\": 252, \\\"name\\\": \\\"User 252 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Flores Freeway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:28\\\"}, {\\\"location_id\\\": 257, \\\"name\\\": \\\"User 257 - London\\\", \\\"plot_no\\\": \\\"Plot 850\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:00\\\"}, {\\\"location_id\\\": 262, \\\"name\\\": \\\"User 262 - London\\\", \\\"plot_no\\\": \\\"Plot 657\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:02\\\"}, {\\\"location_id\\\": 267, \\\"name\\\": \\\"User 267 - London\\\", \\\"plot_no\\\": \\\"Plot 915\\\", \\\"street\\\": \\\"Baxter Drive\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:05\\\"}, {\\\"location_id\\\": 272, \\\"name\\\": \\\"User 272 - London\\\", \\\"plot_no\\\": \\\"Plot 717\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:53\\\"}, {\\\"location_id\\\": 277, \\\"name\\\": \\\"User 277 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:28\\\"}, {\\\"location_id\\\": 282, \\\"name\\\": \\\"User 282 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Williams Village\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:47:36\\\"}, {\\\"location_id\\\": 287, \\\"name\\\": \\\"User 287 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Alvarez Via\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:05\\\"}, {\\\"location_id\\\": 292, \\\"name\\\": \\\"User 292 - London\\\", \\\"plot_no\\\": \\\"Plot 958\\\", \\\"street\\\": \\\"Kara Grove\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:36\\\"}, {\\\"location_id\\\": 297, \\\"name\\\": \\\"User 297 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Ingram Junctions\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:55\\\"}, {\\\"location_id\\\": 302, \\\"name\\\": \\\"User 302 - London\\\", \\\"plot_no\\\": \\\"Plot 361\\\", \\\"street\\\": \\\"Jean Glens\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:04\\\"}, {\\\"location_id\\\": 307, \\\"name\\\": \\\"User 307 - London\\\", \\\"plot_no\\\": \\\"Plot 513\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:46\\\"}, {\\\"location_id\\\": 312, \\\"name\\\": \\\"User 312 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Roberts Valley\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:11\\\"}, {\\\"location_id\\\": 317, \\\"name\\\": \\\"User 317 - London\\\", \\\"plot_no\\\": \\\"Plot 535\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:49\\\"}, {\\\"location_id\\\": 322, \\\"name\\\": \\\"User 322 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Sheila Forest\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:28\\\"}, {\\\"location_id\\\": 327, \\\"name\\\": \\\"User 327 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Michele Forge\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:02\\\"}, {\\\"location_id\\\": 332, \\\"name\\\": \\\"User 332 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"James Landing\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:20\\\"}, {\\\"location_id\\\": 337, \\\"name\\\": \\\"User 337 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:50:27\\\"}, {\\\"location_id\\\": 342, \\\"name\\\": \\\"User 342 - London\\\", \\\"plot_no\\\": \\\"Plot 349\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:50:07\\\"}, {\\\"location_id\\\": 347, \\\"name\\\": \\\"User 347 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:43\\\"}, {\\\"location_id\\\": 352, \\\"name\\\": \\\"User 352 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:25\\\"}, {\\\"location_id\\\": 357, \\\"name\\\": \\\"User 357 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Welch Groves\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:05\\\"}, {\\\"location_id\\\": 362, \\\"name\\\": \\\"User 362 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:06\\\"}, {\\\"location_id\\\": 367, \\\"name\\\": \\\"User 367 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Quinn Loop\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:53\\\"}, {\\\"location_id\\\": 372, \\\"name\\\": \\\"User 372 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Dean Mill\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:14\\\"}, {\\\"location_id\\\": 377, \\\"name\\\": \\\"User 377 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Howard Creek\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:00\\\"}, {\\\"location_id\\\": 382, \\\"name\\\": \\\"User 382 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Acosta Route\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:25\\\"}, {\\\"location_id\\\": 387, \\\"name\\\": \\\"User 387 - London\\\", \\\"plot_no\\\": \\\"Plot 640\\\", \\\"street\\\": \\\"Simpson Island\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:32\\\"}, {\\\"location_id\\\": 392, \\\"name\\\": \\\"User 392 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:51\\\"}, {\\\"location_id\\\": 397, \\\"name\\\": \\\"User 397 - London\\\", \\\"plot_no\\\": \\\"Plot 298\\\", \\\"street\\\": \\\"Wiley Plains\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:44\\\"}, {\\\"location_id\\\": 402, \\\"name\\\": \\\"User 402 - London\\\", \\\"plot_no\\\": \\\"Plot 807\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:22\\\"}, {\\\"location_id\\\": 407, \\\"name\\\": \\\"User 407 - London\\\", \\\"plot_no\\\": \\\"Plot 489\\\", \\\"street\\\": \\\"Kenneth Ford\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:48\\\"}, {\\\"location_id\\\": 412, \\\"name\\\": \\\"User 412 - London\\\", \\\"plot_no\\\": \\\"Plot 941\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:25\\\"}, {\\\"location_id\\\": 417, \\\"name\\\": \\\"User 417 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Douglas Alley\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:01\\\"}, {\\\"location_id\\\": 422, \\\"name\\\": \\\"User 422 - London\\\", \\\"plot_no\\\": \\\"Plot 768\\\", \\\"street\\\": \\\"Patterson Glen\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:02\\\"}, {\\\"location_id\\\": 427, \\\"name\\\": \\\"User 427 - London\\\", \\\"plot_no\\\": \\\"Plot 584\\\", \\\"street\\\": \\\"Tony Locks\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:48\\\"}, {\\\"location_id\\\": 432, \\\"name\\\": \\\"User 432 - London\\\", \\\"plot_no\\\": \\\"Plot 191\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:33\\\"}, {\\\"location_id\\\": 437, \\\"name\\\": \\\"User 437 - London\\\", \\\"plot_no\\\": \\\"Plot 735\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:43\\\"}, {\\\"location_id\\\": 442, \\\"name\\\": \\\"User 442 - London\\\", \\\"plot_no\\\": \\\"Plot 897\\\", \\\"street\\\": \\\"Williams Spurs\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:57\\\"}, {\\\"location_id\\\": 447, \\\"name\\\": \\\"User 447 - London\\\", \\\"plot_no\\\": \\\"Plot 138\\\", \\\"street\\\": \\\"Traci Islands\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:38\\\"}, {\\\"location_id\\\": 452, \\\"name\\\": \\\"User 452 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:20\\\"}, {\\\"location_id\\\": 457, \\\"name\\\": \\\"User 457 - London\\\", \\\"plot_no\\\": \\\"Plot 512\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:24\\\"}, {\\\"location_id\\\": 462, \\\"name\\\": \\\"User 462 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:37\\\"}, {\\\"location_id\\\": 467, \\\"name\\\": \\\"User 467 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Ann Ridges\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:34\\\"}, {\\\"location_id\\\": 472, \\\"name\\\": \\\"User 472 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:57\\\"}, {\\\"location_id\\\": 477, \\\"name\\\": \\\"User 477 - London\\\", \\\"plot_no\\\": \\\"Plot 621\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:54\\\"}, {\\\"location_id\\\": 482, \\\"name\\\": \\\"User 482 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:54\\\"}, {\\\"location_id\\\": 487, \\\"name\\\": \\\"User 487 - London\\\", \\\"plot_no\\\": \\\"Plot 117\\\", \\\"street\\\": \\\"Richard Passage\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:45\\\"}, {\\\"location_id\\\": 492, \\\"name\\\": \\\"User 492 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Newton Shoals\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:52\\\"}, {\\\"location_id\\\": 497, \\\"name\\\": \\\"User 497 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"George Trafficway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:01\\\"}, {\\\"location_id\\\": 502, \\\"name\\\": \\\"User 502 - London\\\", \\\"plot_no\\\": \\\"Plot 632\\\", \\\"street\\\": \\\"Edwards Points\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:16\\\"}, {\\\"location_id\\\": 507, \\\"name\\\": \\\"User 507 - London\\\", \\\"plot_no\\\": \\\"Plot 134\\\", \\\"street\\\": \\\"Jaclyn Prairie\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:28\\\"}, {\\\"location_id\\\": 512, \\\"name\\\": \\\"User 512 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:36\\\"}, {\\\"location_id\\\": 517, \\\"name\\\": \\\"User 517 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Lauren Rapids\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:35\\\"}, {\\\"location_id\\\": 522, \\\"name\\\": \\\"User 522 - London\\\", \\\"plot_no\\\": \\\"Plot 233\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:45\\\"}, {\\\"location_id\\\": 527, \\\"name\\\": \\\"User 527 - London\\\", \\\"plot_no\\\": \\\"Plot 287\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:25\\\"}, {\\\"location_id\\\": 532, \\\"name\\\": \\\"User 532 - London\\\", \\\"plot_no\\\": \\\"Plot 165\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:52\\\"}, {\\\"location_id\\\": 537, \\\"name\\\": \\\"User 537 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Stacey Terrace\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:05\\\"}, {\\\"location_id\\\": 542, \\\"name\\\": \\\"User 542 - London\\\", \\\"plot_no\\\": \\\"Plot 364\\\", \\\"street\\\": \\\"Hernandez Gateway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:50\\\"}, {\\\"location_id\\\": 547, \\\"name\\\": \\\"User 547 - London\\\", \\\"plot_no\\\": \\\"Plot 343\\\", \\\"street\\\": \\\"Carolyn Springs\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:53\\\"}, {\\\"location_id\\\": 552, \\\"name\\\": \\\"User 552 - London\\\", \\\"plot_no\\\": \\\"Plot 575\\\", \\\"street\\\": \\\"Janet Motorway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:49\\\"}, {\\\"location_id\\\": 557, \\\"name\\\": \\\"User 557 - London\\\", \\\"plot_no\\\": \\\"Plot 687\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:43\\\"}, {\\\"location_id\\\": 562, \\\"name\\\": \\\"User 562 - London\\\", \\\"plot_no\\\": \\\"Plot 903\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:45\\\"}, {\\\"location_id\\\": 567, \\\"name\\\": \\\"User 567 - London\\\", \\\"plot_no\\\": \\\"Plot 519\\\", \\\"street\\\": \\\"Anderson Prairie\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:30\\\"}, {\\\"location_id\\\": 572, \\\"name\\\": \\\"User 572 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Jill Crossing\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:23\\\"}, {\\\"location_id\\\": 577, \\\"name\\\": \\\"User 577 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Andrew Dam\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:40\\\"}, {\\\"location_id\\\": 582, \\\"name\\\": \\\"User 582 - London\\\", \\\"plot_no\\\": \\\"Plot 819\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:20\\\"}, {\\\"location_id\\\": 587, \\\"name\\\": \\\"User 587 - London\\\", \\\"plot_no\\\": \\\"Plot 931\\\", \\\"street\\\": \\\"George Lock\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:01\\\"}, {\\\"location_id\\\": 592, \\\"name\\\": \\\"User 592 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:06\\\"}, {\\\"location_id\\\": 597, \\\"name\\\": \\\"User 597 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:55\\\"}, {\\\"location_id\\\": 602, \\\"name\\\": \\\"User 602 - London\\\", \\\"plot_no\\\": \\\"Plot 63\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:21\\\"}, {\\\"location_id\\\": 607, \\\"name\\\": \\\"User 607 - London\\\", \\\"plot_no\\\": \\\"Plot 526\\\", \\\"street\\\": \\\"Julie Extensions\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:10\\\"}, {\\\"location_id\\\": 612, \\\"name\\\": \\\"User 612 - London\\\", \\\"plot_no\\\": \\\"Plot 892\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:21\\\"}, {\\\"location_id\\\": 617, \\\"name\\\": \\\"User 617 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:34\\\"}, {\\\"location_id\\\": 622, \\\"name\\\": \\\"User 622 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:38\\\"}, {\\\"location_id\\\": 627, \\\"name\\\": \\\"User 627 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:20\\\"}, {\\\"location_id\\\": 632, \\\"name\\\": \\\"User 632 - London\\\", \\\"plot_no\\\": \\\"Plot 625\\\", \\\"street\\\": \\\"Anthony Canyon\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:04\\\"}, {\\\"location_id\\\": 637, \\\"name\\\": \\\"User 637 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Ray Row\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:43\\\"}, {\\\"location_id\\\": 642, \\\"name\\\": \\\"User 642 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"James Way\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:42\\\"}, {\\\"location_id\\\": 647, \\\"name\\\": \\\"User 647 - London\\\", \\\"plot_no\\\": \\\"Plot 914\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:58\\\"}, {\\\"location_id\\\": 652, \\\"name\\\": \\\"User 652 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:08\\\"}, {\\\"location_id\\\": 657, \\\"name\\\": \\\"User 657 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Shaw Creek\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:24\\\"}, {\\\"location_id\\\": 662, \\\"name\\\": \\\"User 662 - London\\\", \\\"plot_no\\\": \\\"Plot 663\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:42\\\"}, {\\\"location_id\\\": 667, \\\"name\\\": \\\"User 667 - London\\\", \\\"plot_no\\\": \\\"Plot 392\\\", \\\"street\\\": \\\"Andrew Fords\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:18\\\"}, {\\\"location_id\\\": 672, \\\"name\\\": \\\"User 672 - London\\\", \\\"plot_no\\\": \\\"Plot 35\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:57\\\"}, {\\\"location_id\\\": 677, \\\"name\\\": \\\"User 677 - London\\\", \\\"plot_no\\\": \\\"Plot 278\\\", \\\"street\\\": \\\"James Summit\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:18\\\"}, {\\\"location_id\\\": 682, \\\"name\\\": \\\"User 682 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:27\\\"}, {\\\"location_id\\\": 687, \\\"name\\\": \\\"User 687 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:20\\\"}, {\\\"location_id\\\": 692, \\\"name\\\": \\\"User 692 - London\\\", \\\"plot_no\\\": \\\"Plot 394\\\", \\\"street\\\": \\\"Pratt Curve\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:29\\\"}, {\\\"location_id\\\": 697, \\\"name\\\": \\\"User 697 - London\\\", \\\"plot_no\\\": \\\"Plot 847\\\", \\\"street\\\": \\\"Reed Ville\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:22\\\"}, {\\\"location_id\\\": 702, \\\"name\\\": \\\"User 702 - London\\\", \\\"plot_no\\\": \\\"Plot 407\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:17\\\"}, {\\\"location_id\\\": 707, \\\"name\\\": \\\"User 707 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Mary Island\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:11\\\"}, {\\\"location_id\\\": 712, \\\"name\\\": \\\"User 712 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Murillo Curve\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:33\\\"}, {\\\"location_id\\\": 717, \\\"name\\\": \\\"User 717 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Todd Meadow\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:30\\\"}, {\\\"location_id\\\": 722, \\\"name\\\": \\\"User 722 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:14\\\"}, {\\\"location_id\\\": 727, \\\"name\\\": \\\"User 727 - London\\\", \\\"plot_no\\\": \\\"Plot 109\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:41\\\"}, {\\\"location_id\\\": 732, \\\"name\\\": \\\"User 732 - London\\\", \\\"plot_no\\\": \\\"Plot 54\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:15\\\"}, {\\\"location_id\\\": 737, \\\"name\\\": \\\"User 737 - London\\\", \\\"plot_no\\\": \\\"Plot 514\\\", \\\"street\\\": \\\"Antonio Fords\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:10\\\"}, {\\\"location_id\\\": 742, \\\"name\\\": \\\"User 742 - London\\\", \\\"plot_no\\\": \\\"Plot 177\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:49\\\"}, {\\\"location_id\\\": 747, \\\"name\\\": \\\"User 747 - London\\\", \\\"plot_no\\\": \\\"Plot 138\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:33\\\"}, {\\\"location_id\\\": 752, \\\"name\\\": \\\"User 752 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:30\\\"}, {\\\"location_id\\\": 757, \\\"name\\\": \\\"User 757 - London\\\", \\\"plot_no\\\": \\\"Plot 401\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:01\\\"}, {\\\"location_id\\\": 762, \\\"name\\\": \\\"User 762 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:46\\\"}, {\\\"location_id\\\": 767, \\\"name\\\": \\\"User 767 - London\\\", \\\"plot_no\\\": \\\"Plot 187\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:06\\\"}, {\\\"location_id\\\": 772, \\\"name\\\": \\\"User 772 - London\\\", \\\"plot_no\\\": \\\"Plot 230\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:35\\\"}, {\\\"location_id\\\": 777, \\\"name\\\": \\\"User 777 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:49\\\"}, {\\\"location_id\\\": 782, \\\"name\\\": \\\"User 782 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Regina Throughway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:55\\\"}, {\\\"location_id\\\": 787, \\\"name\\\": \\\"User 787 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:30\\\"}, {\\\"location_id\\\": 792, \\\"name\\\": \\\"User 792 - London\\\", \\\"plot_no\\\": \\\"Plot 451\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:47:23\\\"}, {\\\"location_id\\\": 797, \\\"name\\\": \\\"User 797 - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:53\\\"}, {\\\"location_id\\\": 808, \\\"name\\\": \\\"Acme Systems Site A - London\\\", \\\"plot_no\\\": \\\"Plot 45\\\", \\\"street\\\": \\\"Miller Plain\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:11\\\"}, {\\\"location_id\\\": 815, \\\"name\\\": \\\"Wayne Enterprises Hq - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:38\\\"}, {\\\"location_id\\\": 817, \\\"name\\\": \\\"Stark Industries Hq - London\\\", \\\"plot_no\\\": \\\"Plot 93\\\", \\\"street\\\": \\\"Webb Curve\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:36\\\"}, {\\\"location_id\\\": 818, \\\"name\\\": \\\"Stark Industries Site A - London\\\", \\\"plot_no\\\": \\\"Plot 25\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:16\\\"}, {\\\"location_id\\\": 825, \\\"name\\\": \\\"Massive Dynamic Hq - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:36\\\"}, {\\\"location_id\\\": 830, \\\"name\\\": \\\"Smith, Mcpherson And Hudson Site A - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:46\\\"}, {\\\"location_id\\\": 834, \\\"name\\\": \\\"Wilson And Sons Site A - London\\\", \\\"plot_no\\\": \\\"Plot 644\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:11\\\"}, {\\\"location_id\\\": 839, \\\"name\\\": \\\"Carrillo Inc Hq - London\\\", \\\"plot_no\\\": \\\"Plot 615\\\", \\\"street\\\": \\\"Nelson Lane\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:47:03\\\"}, {\\\"location_id\\\": 852, \\\"name\\\": \\\"Miller-Willis Site A - London\\\", \\\"plot_no\\\": \\\"Plot 748\\\", \\\"street\\\": \\\"Kelley Gateway\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:18\\\"}, {\\\"location_id\\\": 862, \\\"name\\\": \\\"Johnson, Rivera And Carr Site A - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:40\\\"}, {\\\"location_id\\\": 878, \\\"name\\\": \\\"Stark, Petersen And Palmer Site A - London\\\", \\\"plot_no\\\": null, \\\"street\\\": \\\"Amy Inlet\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:48:06\\\"}, {\\\"location_id\\\": 881, \\\"name\\\": \\\"Russell, Johnson And Clark Hq - London\\\", \\\"plot_no\\\": \\\"Plot 638\\\", \\\"street\\\": \\\"Evans Pines\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:31\\\"}, {\\\"location_id\\\": 891, \\\"name\\\": \\\"Simon Llc Hq - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:31\\\"}, {\\\"location_id\\\": 896, \\\"name\\\": \\\"Cox, Foster And Gilmore Site A - London\\\", \\\"plot_no\\\": null, \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:00\\\"}, {\\\"location_id\\\": 901, \\\"name\\\": \\\"Owen, Leonard And Chapman Hq - London\\\", \\\"plot_no\\\": \\\"Plot 859\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:17\\\"}, {\\\"location_id\\\": 903, \\\"name\\\": \\\"Smith Llc Hq - London\\\", \\\"plot_no\\\": \\\"Plot 586\\\", \\\"street\\\": null, \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:43\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"serial_number\":\"P25\"}","call_id":"call_3jh9APkWhJUZpOR95A5PZdjf","name":"retrieve_installed_products","type":"function_call","id":"fc_031533b1546483e4006a63f46504b88195b5608d94b3754540","status":"completed"},{"call_id":"call_3jh9APkWhJUZpOR95A5PZdjf","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"installed_product_id\\\": 15, \\\"account_id\\\": 3, \\\"product_id\\\": 25, \\\"location_id\\\": 808, \\\"serial_number\\\": \\\"P25-390837-3986\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2029-07-07\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:36:08\\\"}, {\\\"installed_product_id\\\": 40, \\\"account_id\\\": 8, \\\"product_id\\\": 25, \\\"location_id\\\": 817, \\\"serial_number\\\": \\\"P25-458046-6504\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2027-06-18\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:48:23\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"location_id\":808}","call_id":"call_dLi2GUQ9XO3zI6YyChluJ3sP","name":"find_locations","type":"function_call","id":"fc_031533b1546483e4006a63f4671f28819581f798748c172eef","status":"completed"},{"call_id":"call_dLi2GUQ9XO3zI6YyChluJ3sP","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"location_id\\\": 808, \\\"name\\\": \\\"Acme Systems Site A - London\\\", \\\"plot_no\\\": \\\"Plot 45\\\", \\\"street\\\": \\\"Miller Plain\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:11\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"city\":\"london\",\"street\":\"Pratt Curve\"}","call_id":"call_8hZwjLNWBZVM3Eht5MgA00v6","name":"find_locations","type":"function_call","id":"fc_031533b1546483e4006a63f46931ac81959d5ccae584080bba","status":"completed"},{"call_id":"call_8hZwjLNWBZVM3Eht5MgA00v6","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"location_id\\\": 692, \\\"name\\\": \\\"User 692 - London\\\", \\\"plot_no\\\": \\\"Plot 394\\\", \\\"street\\\": \\\"Pratt Curve\\\", \\\"city\\\": \\\"london\\\", \\\"country\\\": \\\"uk\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:29\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"installed_product_id\":15,\"location_id\":692,\"status\":\"in_use\"}","call_id":"call_zfZ2hg8WvGwZBVcdkDWpKRET","name":"update_installed_product_details","type":"function_call","id":"fc_031533b1546483e4006a63f46b7dec8195b63f5771154f8244","status":"completed"},{"call_id":"call_zfZ2hg8WvGwZBVcdkDWpKRET","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"installed_product_id\\\": 15, \\\"account_id\\\": 3, \\\"product_id\\\": 25, \\\"location_id\\\": 692, \\\"serial_number\\\": \\\"P25-390837-3986\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2029-07-07\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:36:08\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:32\\\"}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"account_id\":3,\"active\":true}","call_id":"call_u0gzPJKc6MOAKa4k9oy3nnYC","name":"find_contacts","type":"function_call","id":"fc_031533b1546483e4006a63f46dd610819586d71ac114042350","status":"completed"},{"call_id":"call_u0gzPJKc6MOAKa4k9oy3nnYC","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"contact_id\\\": 1, \\\"account_id\\\": 3, \\\"portal_user_id\\\": 47, \\\"active\\\": 1, \\\"is_primary\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:35\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"user_id\":47}","call_id":"call_L55kPjGV8ZrhvJXON8hH7gu5","name":"list_users","type":"function_call","id":"fc_031533b1546483e4006a63f47000fc8195855bb2f4b0781a3e","status":"completed"},{"call_id":"call_L55kPjGV8ZrhvJXON8hH7gu5","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"user_id\\\": 47, \\\"first_name\\\": \\\"Michael\\\", \\\"last_name\\\": \\\"Ward\\\", \\\"email\\\": \\\"michael.ward53@acme.com\\\", \\\"phone\\\": \\\"+917398556557\\\", \\\"role\\\": \\\"customer\\\", \\\"location_id\\\": 47, \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:02\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"case_id\":0,\"email\":\"michael.ward53@acme.com\",\"type\":\"update\"}","call_id":"call_STOxz5hNUIvA8pllytbDAnmX","name":"send_notification","type":"function_call","id":"fc_031533b1546483e4006a63f47284d88195b45d2b610541ffc0","status":"completed"},{"call_id":"call_STOxz5hNUIvA8pllytbDAnmX","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [send_notification]: Invalid case_id\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"id":"msg_031533b1546483e4006a63f475732c8195b2f70e64bc485072","content":[{"annotations":[],"text":"The device with serial number P25-390837-3986 has been successfully relocated to the London site at Plot 394, Pratt Curve, and its status remains operational. I have identified the primary contact for the associated account as Michael Ward (email: michael.ward53@acme.com). However, to send a notification about this update, I need a related case ID. If you want, I can help create a case for this update and then send the notification. Please confirm if you want to proceed with case creation.","type":"output_text","logprobs":[]}],"role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"temperature":0.0,"tool_choice":"auto","tools":[{"name":"list_users","parameters":{"type":"object","properties":{"email":{"type":"string","description":"Filter by user email address (exact match) (unique)."},"user_id":{"type":"integer","description":"Filter by unique user identifier."},"first_name":{"type":"string","description":"Filter by user's first name."},"last_name":{"type":"string","description":"Filter by user's last name."},"phone":{"type":"string","description":"Filter by phone number."},"role":{"type":"string","enum":["admin","agent","manager","customer"],"description":"Filter by user role (admin, agent, manager, or customer)."},"location_id":{"type":"integer","description":"Filter by location identifier."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"created_after":{"type":"string","description":"Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned.","defer_loading":null},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.","defer_loading":null},{"name":"find_locations","parameters":{"type":"object","properties":{"location_id":{"type":"integer","description":"Unique identifier of the location."},"name":{"type":"string","description":"Name of the location."},"active":{"type":"boolean","description":"Whether the location is currently active."},"plot_no":{"type":"string","description":"Plot number of the location."},"street":{"type":"string","description":"Street address of the location."},"city":{"type":"string","description":"City where the location is situated."},"country":{"type":"string","description":"Country where the location is situated."},"created_before":{"type":"string","description":"Filter for locations created before this timestamp (ISO format)."},"created_after":{"type":"string","description":"Filter for locations created after this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.","defer_loading":null},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.","defer_loading":null},{"name":"update_installed_product_details","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID (required)."},"location_id":{"type":"integer","description":"Location/site ID where the product is installed."},"account_id":{"type":"integer","description":"Owning account ID for this installed product."},"product_id":{"type":"integer","description":"Product ID that was installed."},"serial_number":{"type":"string","description":"Unique serial number of the installed product.","minLength":1},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Status of the installed product."},"warranty_end":{"type":"string","description":"Warranty end date (YYYY-MM-DD)."}},"required":["installed_product_id"]},"strict":false,"type":"function","description":"Update an installed product (partial updates allowed). Combination of Account ID, Product ID, Serial Number should be unique.","defer_loading":null},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"send_notification","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Case ID this notification is related to."},"knowledge_id":{"type":"integer","description":"Optional knowledge article ID linked to this notification."},"email":{"type":"string","description":"Recipient email address of the notification.","minLength":1},"type":{"type":"string","enum":["report","update","alert","reminder","solution_proposal","next_steps","other"],"description":"Type of notification being sent."}},"required":["case_id","email","type"]},"strict":false,"type":"function","description":"Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.","defer_loading":null}],"top_p":1.0,"background":false,"conversation":null,"max_output_tokens":16384,"max_tool_calls":null,"previous_response_id":null,"prompt":null,"prompt_cache_key":null,"reasoning":{"effort":null,"generate_summary":null,"summary":null,"context":null},"safety_identifier":null,"service_tier":"default","status":"completed","text":{"format":{"type":"text"},"verbosity":"medium"},"top_logprobs":0,"truncation":"disabled","usage":{"input_tokens":140083,"input_tokens_details":{"cached_tokens":0,"audio_tokens":null,"text_tokens":null},"output_tokens":280,"output_tokens_details":{"reasoning_tokens":0,"text_tokens":null},"total_tokens":140363,"cost":null},"user":null,"store":true,"completed_at":1784935542,"content_filters":[{"blocked":false,"source_type":"completion","content_filter_raw":[],"content_filter_results":{"protected_material_code":{"detected":false,"filtered":false},"protected_material_text":{"detected":false,"filtered":false},"hate":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"start_offset":0,"end_offset":494,"check_offset":0}}],"frequency_penalty":0.0,"moderation":null,"presence_penalty":0.0,"prompt_cache_retention":"in_memory"},"reward":0.0,"overall_success":false,"verifier_pass_rate":0.0,"verification_results":{"Verify Updated Installed Product":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) \nFROM installed_product AS ip\nWHERE ip.installed_product_id = 40\n AND ip.location_id = 692\n AND ip.status = 'in_use';\n","details":"Comparison equals: 0 vs 1"},"Verify Create New Case":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*)\nFROM customer_case AS c\nWHERE c.account_id = 8\n AND c.contact_id = 10\n AND c.channel = 'alert'\n AND c.priority = 'low'\n AND c.state = 'closed';\n ","details":"Comparison equals: 0 vs 1"},"Verify Notification Sent ":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'tonya.stevens@stark-industries.com'\n AND n.type = 'update';\n","details":"Comparison equals: 0 vs 1"}},"strict_success":false,"strict_pass_rate":0.0,"num_verifiers_defined":4,"num_verifiers_scored":3,"num_tool_calls":8,"tool_latencies_ms":[{"tool":"find_locations","gym":"sn-csm-server","latency_ms":15.7},{"tool":"retrieve_installed_products","gym":"sn-csm-server","latency_ms":11.0},{"tool":"find_locations","gym":"sn-csm-server","latency_ms":10.3},{"tool":"find_locations","gym":"sn-csm-server","latency_ms":11.0},{"tool":"update_installed_product_details","gym":"sn-csm-server","latency_ms":15.7},{"tool":"find_contacts","gym":"sn-csm-server","latency_ms":9.7},{"tool":"list_users","gym":"sn-csm-server","latency_ms":20.2},{"tool":"send_notification","gym":"sn-csm-server","latency_ms":10.9}],"verifier_metadata":{"task_id":"task_20251205_154853_044_d4a463c3_fce76046","domain":"csm","mode":"oracle","gym_servers_config":[{"mcp_server_name":"sn-csm-server","mcp_server_url":"http://localhost:8001","seed_database_file":"Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql","context":{"x-user-email":"jose.roberson@servicenow.com"},"user_info":""}],"verifiers":[{"verifier_type":"database_state","name":"Verify Updated Installed Product","description":"Verify Updated Installed Product","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) \nFROM installed_product AS ip\nWHERE ip.installed_product_id = 40\n AND ip.location_id = 692\n AND ip.status = 'in_use';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify Create New Case","description":"Verify Create New Case","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*)\nFROM customer_case AS c\nWHERE c.account_id = 8\n AND c.contact_id = 10\n AND c.channel = 'alert'\n AND c.priority = 'low'\n AND c.state = 'closed';\n ","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify Notification Sent ","description":"Verify Notification Sent ","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'marc.henry@stark-industries.com'\n AND n.type = 'update';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify Notification Sent ","description":"Verify Notification Sent ","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*)\nFROM notification AS n\nWHERE n.case_id = 1233\n AND n.email = 'tonya.stevens@stark-industries.com'\n AND n.type = 'update';\n","expected_value":1,"comparison_type":"equals"}}],"selected_tools":["update_case","send_notification","create_new_case","find_locations","find_contacts","update_installed_product_details","list_users","retrieve_installed_products"],"restricted_tools":[],"tool_to_gym":{"list_users":"sn-csm-server","find_contacts":"sn-csm-server","find_locations":"sn-csm-server","retrieve_installed_products":"sn-csm-server","update_installed_product_details":"sn-csm-server","create_new_case":"sn-csm-server","update_case":"sn-csm-server","send_notification":"sn-csm-server"}},"agent_ref":{"name":"enterpriseops_gym_simple_agent"},"_ng_task_index":1,"_ng_rollout_index":0}
+{"responses_create_params":{"background":null,"include":null,"input":[{"content":"CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided → default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new → in_progress, in_progress → pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new → in_progress / pending / resolved in_progress → pending / resolved pending → in_progress / resolved resolved → closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid → inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30–120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities.","role":"system","type":"message"},{"content":"As part of a readiness check for a new business-critical service and the broader rollout, a few coordinated updates are required. First, confirm that Curtis Mccoy is active and ready to take on high-impact responsibilities along with his team for this rollout. Then register a new active service named “Network Resilience Health Check”, and create an internal troubleshooting guide titled “Network Resilience Health Check Troubleshooting” for it.\n\nWithdraw the incorrectly opened case CS-0000888 for Stark, Petersen and Palmer so it no longer affects workload reporting. Next, create a phone-reported support case for the same account related to operational instability tied to this service. Validate entitlement coverage,route the case using the handling method currently in place for this implementation, link the troubleshooting guide as a suggested reference, apply the critical-response SLA, and ensure the case is positioned for immediate technical action with proper priority due to the high business risk involved.","role":"user","type":"message"}],"instructions":null,"max_output_tokens":16384,"max_tool_calls":null,"metadata":null,"model":null,"parallel_tool_calls":true,"previous_response_id":null,"prompt":null,"reasoning":null,"service_tier":null,"store":null,"temperature":0.0,"text":null,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name."},{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business."},{"name":"list_user_groups","parameters":{"type":"object","properties":{"group_id":{"type":"integer","description":"Filter by unique group identifier."},"name":{"type":"string","description":"Filter by group name (exact match, unique)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"type":{"type":"string","enum":["support","backoffice","field","vendor"],"description":"Filter by group type (support, backoffice, field, vendor)."},"created_after":{"type":"string","description":"Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user groups with optional filters."},{"name":"list_group_members","parameters":{"type":"object","properties":{"member_id":{"type":"integer","description":"Filter by unique membership identifier."},"group_id":{"type":"integer","description":"Filter by group identifier."},"user_id":{"type":"integer","description":"Filter by user identifier."},"created_after":{"type":"string","description":"Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user group members with optional filters. Combination of group_id and user_id is unique."},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact."},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement."},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority."},{"name":"search_cases","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case."},"number":{"type":"string","description":"Case number (unique human-readable reference)."},"account_id":{"type":"integer","description":"Filter by account ID. An account represents a business entity or organization."},"contact_id":{"type":"integer","description":"Filter by contact ID."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"installed_product_id":{"type":"integer","description":"Filter by installed product ID. Unique identifier which relates to the installed product table record."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was communicated/created."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"State of the case."},"short_description":{"type":"string","description":"Short description of the case."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation."},"reopen_count":{"type":"integer","description":"Filter by number of times the case was reopened."},"closed_on":{"type":"string","description":"Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return cases created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution."},{"name":"add_new_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Name of the product (e.g., 'Premium Support Package') (unique).","minLength":1},"category":{"type":"string","enum":["software","hardware","service"],"description":"Product category (software, hardware, or service)."},"lifecycle_state":{"type":"string","enum":["active","retired"],"description":"Lifecycle state of the product (active or retired)."},"product_price":{"type":"integer","description":"Price of the product in the smallest currency unit (e.g., cents)."}},"required":["name","category","lifecycle_state"]},"strict":false,"type":"function","description":"Create/register a product. Add product details. Products can be software, hardware, or services offered by the organization."},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case."},{"name":"create_knowledge","parameters":{"type":"object","properties":{"title":{"type":"string","description":"Title of the knowledge article.","minLength":1},"state":{"type":"string","enum":["draft","published","retired"],"description":"Lifecycle state of the article."},"body":{"type":"string","description":"Body of the knowledge article."},"visibility":{"type":"string","enum":["internal","external"],"description":"Who can view the article: internal staff or external customers."},"product_id":{"type":"integer","description":"ID of the related product, if applicable."},"owner_id":{"type":"integer","description":"User ID of the article owner/author."}},"required":["title","state","body","visibility","owner_id"]},"strict":false,"type":"function","description":"Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff."},{"name":"link_case_knowledge","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case being linked."},"knowledge_id":{"type":"integer","description":"Unique identifier of the knowledge article to link."},"used_as":{"type":"string","enum":["suggested","applied","resolution"],"description":"Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}},"required":["case_id","knowledge_id","used_as"]},"strict":false,"type":"function","description":"Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case."}],"top_logprobs":null,"top_p":null,"truncation":null,"user":null,"stream":null},"response":{"id":"resp_gaNuZZdjmkLuIRwwcl8mJspqzikJzQyu5LLNn_-ykNgHHa4_U27Fbpj6ttKRmHQt0JaE6GMjBtL6fQMwm2AmjPPUTZV2VBrFKOvEw0BoSOBaovTdJBZJBnyc9iNUovhznnwe2nfmGjfNh2KYJgdVISqI-nfcaYIJhp9KKKy60yTBKvBeyY1RMJ83XWZZQ7weIxnKkYyCgcYO5qjFOdDGvzEP4UP0i6mp43uXrlV4LQw2Gz9Dhjm5mWnxrwveDht_Dx-vgo6lCSR7ORKHnLaW0TO4u7S7ALVEHxnlvf57Yu34DKgTwab22Q_eZnfdB2ejyu-FvADd6A5VBcp4RIJFKRZ17b23JK44OqTq1b-L_c94PSBmo03h_h7LYQucCftkI4_y4oiMWQYZm5Qmicw=","created_at":1784935569.0,"error":null,"incomplete_details":null,"instructions":null,"metadata":{},"model":"azure/openai/gpt-4.1-mini","object":"response","output":[{"arguments":"{\"name\":\"Curtis Mccoy\"}","call_id":"call_wr2VmR6dXjyBkMV1gKaXZO75","name":"find_user","type":"function_call","id":"fc_055f6e21b6fb0470006a63f463b3f0819397bdb1303c0af8b4","status":"completed"},{"arguments":"{\"name\":\"Stark, Petersen and Palmer\"}","call_id":"call_r1RkoMVe8Juz9ltRyEHNk00Z","name":"find_account","type":"function_call","id":"fc_055f6e21b6fb0470006a63f463b4048193aee1fbf0c48ef743","status":"completed"},{"call_id":"call_wr2VmR6dXjyBkMV1gKaXZO75","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"user_id\\\": 177, \\\"first_name\\\": \\\"Curtis\\\", \\\"last_name\\\": \\\"Mccoy\\\", \\\"email\\\": \\\"curtis.mccoy@servicenow.com\\\", \\\"role\\\": \\\"manager\\\", \\\"location_id\\\": 177, \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_r1RkoMVe8Juz9ltRyEHNk00Z","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"account_id\\\": 38, \\\"name\\\": \\\"Stark, Petersen and Palmer\\\", \\\"account_type\\\": \\\"customer\\\", \\\"email_domain\\\": \\\"starkpetersenandpalmer.com\\\", \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"type\":\"support\",\"active\":true}","call_id":"call_6X3LbE6Fo0IRgnAeJ9mKwn83","name":"list_user_groups","type":"function_call","id":"fc_055f6e21b6fb0470006a63f46563408193bcb1d59127cc0309","status":"completed"},{"call_id":"call_6X3LbE6Fo0IRgnAeJ9mKwn83","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"group_id\\\": 1, \\\"name\\\": \\\"CSM Tier 1 Support\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:32\\\"}, {\\\"group_id\\\": 3, \\\"name\\\": \\\"Case Triage\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:09\\\"}, {\\\"group_id\\\": 4, \\\"name\\\": \\\"Case Assignment\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:37\\\"}, {\\\"group_id\\\": 5, \\\"name\\\": \\\"Entitlement Verification\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:22\\\"}, {\\\"group_id\\\": 6, \\\"name\\\": \\\"Contract & Warranty Desk\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:30\\\"}, {\\\"group_id\\\": 7, \\\"name\\\": \\\"Account Management\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:06\\\"}, {\\\"group_id\\\": 10, \\\"name\\\": \\\"Installed Base Support\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:32\\\"}, {\\\"group_id\\\": 11, \\\"name\\\": \\\"Proactive Case Monitoring\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:55\\\"}, {\\\"group_id\\\": 12, \\\"name\\\": \\\"Vendor Case Liaison\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:46\\\"}, {\\\"group_id\\\": 13, \\\"name\\\": \\\"Knowledge Curation\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:31\\\"}, {\\\"group_id\\\": 16, \\\"name\\\": \\\"Customer Onboarding\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:25\\\"}, {\\\"group_id\\\": 18, \\\"name\\\": \\\"Escalation Management\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:10\\\"}, {\\\"group_id\\\": 19, \\\"name\\\": \\\"Customer Health Monitoring\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:35\\\"}, {\\\"group_id\\\": 20, \\\"name\\\": \\\"Billing & Adjustments\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:29:47\\\"}, {\\\"group_id\\\": 21, \\\"name\\\": \\\"CSM Tier 1 Support_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:05\\\"}, {\\\"group_id\\\": 24, \\\"name\\\": \\\"Case Assignment_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:04\\\"}, {\\\"group_id\\\": 25, \\\"name\\\": \\\"Entitlement Verification_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:55\\\"}, {\\\"group_id\\\": 26, \\\"name\\\": \\\"Contract & Warranty Desk_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:47:53\\\"}, {\\\"group_id\\\": 27, \\\"name\\\": \\\"Account Management_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:34\\\"}, {\\\"group_id\\\": 28, \\\"name\\\": \\\"Contact Center L1_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:50\\\"}, {\\\"group_id\\\": 30, \\\"name\\\": \\\"Installed Base Support_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:02\\\"}, {\\\"group_id\\\": 31, \\\"name\\\": \\\"Proactive Case Monitoring_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:11\\\"}, {\\\"group_id\\\": 33, \\\"name\\\": \\\"Knowledge Curation_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:44\\\"}, {\\\"group_id\\\": 34, \\\"name\\\": \\\"Field Service Coordination_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:41:22\\\"}, {\\\"group_id\\\": 38, \\\"name\\\": \\\"Escalation Management_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:48\\\"}, {\\\"group_id\\\": 39, \\\"name\\\": \\\"Customer Health Monitoring_2\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:30:15\\\"}, {\\\"group_id\\\": 41, \\\"name\\\": \\\"CSM Tier 1 Support_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:11\\\"}, {\\\"group_id\\\": 42, \\\"name\\\": \\\"CSM Tier 2 Support_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:50:24\\\"}, {\\\"group_id\\\": 43, \\\"name\\\": \\\"Case Triage_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:47:28\\\"}, {\\\"group_id\\\": 44, \\\"name\\\": \\\"Case Assignment_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:54\\\"}, {\\\"group_id\\\": 45, \\\"name\\\": \\\"Entitlement Verification_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:05\\\"}, {\\\"group_id\\\": 46, \\\"name\\\": \\\"Contract & Warranty Desk_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:12\\\"}, {\\\"group_id\\\": 47, \\\"name\\\": \\\"Account Management_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:40:39\\\"}, {\\\"group_id\\\": 48, \\\"name\\\": \\\"Contact Center L1_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:26\\\"}, {\\\"group_id\\\": 49, \\\"name\\\": \\\"Contact Center L2_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:37:57\\\"}, {\\\"group_id\\\": 52, \\\"name\\\": \\\"Vendor Case Liaison_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:55\\\"}, {\\\"group_id\\\": 56, \\\"name\\\": \\\"Customer Onboarding_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:49:15\\\"}, {\\\"group_id\\\": 57, \\\"name\\\": \\\"Renewals & Retention_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:34:50\\\"}, {\\\"group_id\\\": 60, \\\"name\\\": \\\"Billing & Adjustments_3\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:33\\\"}, {\\\"group_id\\\": 63, \\\"name\\\": \\\"Case Triage_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:44\\\"}, {\\\"group_id\\\": 64, \\\"name\\\": \\\"Case Assignment_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:46:24\\\"}, {\\\"group_id\\\": 65, \\\"name\\\": \\\"Entitlement Verification_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:56\\\"}, {\\\"group_id\\\": 68, \\\"name\\\": \\\"Contact Center L1_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:48\\\"}, {\\\"group_id\\\": 69, \\\"name\\\": \\\"Contact Center L2_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:44:07\\\"}, {\\\"group_id\\\": 70, \\\"name\\\": \\\"Installed Base Support_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:41\\\"}, {\\\"group_id\\\": 72, \\\"name\\\": \\\"Vendor Case Liaison_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:43\\\"}, {\\\"group_id\\\": 73, \\\"name\\\": \\\"Knowledge Curation_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:38:41\\\"}, {\\\"group_id\\\": 76, \\\"name\\\": \\\"Customer Onboarding_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:33:09\\\"}, {\\\"group_id\\\": 77, \\\"name\\\": \\\"Renewals & Retention_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:42:45\\\"}, {\\\"group_id\\\": 79, \\\"name\\\": \\\"Customer Health Monitoring_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:45:48\\\"}, {\\\"group_id\\\": 80, \\\"name\\\": \\\"Billing & Adjustments_4\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:57\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"group_id\":1,\"user_id\":177}","call_id":"call_gSQkb3m2hSTZl2hk6POWDJql","name":"list_group_members","type":"function_call","id":"fc_055f6e21b6fb0470006a63f467387c8193a3965a2cee19b849","status":"completed"},{"call_id":"call_gSQkb3m2hSTZl2hk6POWDJql","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"user_id\":177}","call_id":"call_cAWG7jTLLhOEFeEg7fmm28Ie","name":"list_group_members","type":"function_call","id":"fc_055f6e21b6fb0470006a63f468f5c481938769364f981a23f6","status":"completed"},{"call_id":"call_cAWG7jTLLhOEFeEg7fmm28Ie","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"member_id\\\": 18, \\\"group_id\\\": 18, \\\"user_id\\\": 177, \\\"sys_created_on\\\": \\\"2025-08-27 15:43:49\\\"}, {\\\"member_id\\\": 425, \\\"group_id\\\": 75, \\\"user_id\\\": 177, \\\"sys_created_on\\\": \\\"2025-08-27 15:32:21\\\"}, {\\\"member_id\\\": 744, \\\"group_id\\\": 71, \\\"user_id\\\": 177, \\\"sys_created_on\\\": \\\"2025-08-27 15:39:05\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"name\":\"Network Resilience Health Check\",\"category\":\"service\",\"lifecycle_state\":\"active\"}","call_id":"call_xGNMVhhf1aeQNPwHAIr6GKm5","name":"add_new_product","type":"function_call","id":"fc_055f6e21b6fb0470006a63f46b0a5c8193b9aa9fd1bab6a7ed","status":"completed"},{"arguments":"{\"number\":\"CS-0000888\",\"account_id\":38}","call_id":"call_8XhlDeTXOCoB0pHfnGdD8JVW","name":"search_cases","type":"function_call","id":"fc_055f6e21b6fb0470006a63f46b0a7481939c67e0ce0c9b563e","status":"completed"},{"call_id":"call_xGNMVhhf1aeQNPwHAIr6GKm5","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"product_id\\\": 241, \\\"name\\\": \\\"Network Resilience Health Check\\\", \\\"category\\\": \\\"service\\\", \\\"product_price\\\": null, \\\"lifecycle_state\\\": \\\"active\\\", \\\"sys_created_on\\\": \\\"2026-07-24 23:25:31\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:31\\\"}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_8XhlDeTXOCoB0pHfnGdD8JVW","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"case_id\\\": 888, \\\"number\\\": \\\"CS-0000888\\\", \\\"account_id\\\": 38, \\\"contact_id\\\": 85, \\\"product_id\\\": 156, \\\"installed_product_id\\\": 210, \\\"channel\\\": \\\"email\\\", \\\"priority\\\": \\\"low\\\", \\\"state\\\": \\\"in_progress\\\", \\\"short_description\\\": \\\"Product: APC Smart-UPS SRT3000 Variant 24, Issue: is not working as expected.\\\", \\\"escalation\\\": 0, \\\"escalation_reason\\\": null, \\\"reopen_count\\\": 0, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:55\\\", \\\"sys_updated_on\\\": \\\"2025-11-01 03:16:13\\\", \\\"closed_on\\\": null, \\\"assignment_group_id\\\": null, \\\"assigned_to\\\": null}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"case_id\":888,\"state\":\"canceled\"}","call_id":"call_1G0mIFTY60Qbdt3DYLVitURA","name":"update_case","type":"function_call","id":"fc_055f6e21b6fb0470006a63f46ccbac819384ef9e03bfc01d35","status":"completed"},{"call_id":"call_1G0mIFTY60Qbdt3DYLVitURA","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"case_id\\\": 888, \\\"number\\\": \\\"CS-0000888\\\", \\\"account_id\\\": 38, \\\"contact_id\\\": 85, \\\"product_id\\\": 156, \\\"installed_product_id\\\": 210, \\\"channel\\\": \\\"email\\\", \\\"priority\\\": \\\"low\\\", \\\"state\\\": \\\"canceled\\\", \\\"short_description\\\": \\\"Product: APC Smart-UPS SRT3000 Variant 24, Issue: is not working as expected.\\\", \\\"assignment_group_id\\\": null, \\\"assigned_to\\\": null, \\\"escalation\\\": 0, \\\"escalation_reason\\\": null, \\\"reopen_count\\\": 0, \\\"sys_created_on\\\": \\\"2025-08-27 15:36:55\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:33\\\", \\\"closed_on\\\": null}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"account_id\":38,\"active\":true}","call_id":"call_AFgH6vx2Aq54a8a5boNxLfmz","name":"find_contacts","type":"function_call","id":"fc_055f6e21b6fb0470006a63f46ea2dc81939971a2bd7470bacc","status":"completed"},{"call_id":"call_AFgH6vx2Aq54a8a5boNxLfmz","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"contact_id\\\": 84, \\\"account_id\\\": 38, \\\"portal_user_id\\\": 14, \\\"active\\\": 1, \\\"is_primary\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:43\\\"}, {\\\"contact_id\\\": 85, \\\"account_id\\\": 38, \\\"portal_user_id\\\": 215, \\\"active\\\": 1, \\\"is_primary\\\": 0, \\\"sys_created_on\\\": \\\"2025-08-27 15:31:16\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"account_id\":38,\"product_id\":241,\"active\":true}","call_id":"call_qo5mYiRplOKHFAJNv0JzSlib","name":"find_entitlements","type":"function_call","id":"fc_055f6e21b6fb0470006a63f4711b5c8193b12c065c7d544dad","status":"completed"},{"arguments":"{\"account_id\":38,\"contact_id\":84,\"product_id\":241,\"channel\":\"phone\",\"priority\":\"critical\",\"state\":\"new\",\"short_description\":\"Product: Network Resilience Health Check, Issue: operational instability tied to this service.\"}","call_id":"call_5liBcEZQmOcwukDoiJI0Xzsn","name":"create_new_case","type":"function_call","id":"fc_055f6e21b6fb0470006a63f4711b788193986cc4c6ce69aca9","status":"completed"},{"call_id":"call_qo5mYiRplOKHFAJNv0JzSlib","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_5liBcEZQmOcwukDoiJI0Xzsn","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"case_id\\\": 1233, \\\"number\\\": \\\"CS-0001233\\\", \\\"account_id\\\": 38, \\\"contact_id\\\": 84, \\\"product_id\\\": 241, \\\"installed_product_id\\\": null, \\\"channel\\\": \\\"phone\\\", \\\"priority\\\": \\\"critical\\\", \\\"state\\\": \\\"new\\\", \\\"short_description\\\": \\\"Product: Network Resilience Health Check, Issue: operational instability tied to this service.\\\", \\\"assignment_group_id\\\": null, \\\"assigned_to\\\": null, \\\"escalation\\\": 0, \\\"escalation_reason\\\": null, \\\"reopen_count\\\": 0, \\\"sys_created_on\\\": \\\"2026-07-24 23:25:37\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:37\\\", \\\"closed_on\\\": null}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps to resolve the issue: Check network configurations, verify resilience protocols, monitor system logs, and escalate if needed. Suggested Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_qXETHl2zLcTU0VgTKXrpihvS","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f4731b308193b34d5e953ea76c8c","status":"completed"},{"call_id":"call_qXETHl2zLcTU0VgTKXrpihvS","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps to resolve the issue: Check network configurations, verify resilience protocols, monitor system logs, and escalate if needed. Suggested Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps to resolve the issue: Check network configurations and verify resilience protocols. Suggested Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_5BHlHSVrNmpiEwzNeAD9x8gt","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f47554ac81938c49d117d9397290","status":"completed"},{"call_id":"call_5BHlHSVrNmpiEwzNeAD9x8gt","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps to resolve the issue: Check network configurations and verify resilience protocols. Suggested Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check network configs, verify protocols. Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_NMVmo3OgEGvbXgpGBIkXxlJg","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f47806708193bd0b3217e404f95e","status":"completed"},{"call_id":"call_NMVmo3OgEGvbXgpGBIkXxlJg","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'This kind of issues are tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check network configs, verify protocols. Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"Issues tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_wY0nQ5TGAJCOe5XkKF1usKxo","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f47a6fa48193993774ca45aedf59","status":"completed"},{"call_id":"call_wY0nQ5TGAJCOe5XkKF1usKxo","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'Issues tackled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"Handled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_x14sUsyHemu50AOKcMqtEp7h","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f47c9e888193b624509eda49861b","status":"completed"},{"call_id":"call_x14sUsyHemu50AOKcMqtEp7h","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'Handled by Assignment Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"Handled by Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_EskZgBVkGxR5lXmrmFzlYalo","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f4815b9c8193872fd2c95b2f324e","status":"completed"},{"call_id":"call_EskZgBVkGxR5lXmrmFzlYalo","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"API Error [create_knowledge]: [{'type': 'string_too_long', 'loc': ['body', 'body'], 'msg': 'String should have at most 120 characters', 'input': 'Handled by Group: Case Assignment, Assigned to: Curtis Mccoy. Steps: Check configs, verify protocols. Priority: critical.', 'ctx': {'max_length': 120}}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": true}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"title\":\"Network Resilience Health Check Troubleshooting\",\"state\":\"published\",\"body\":\"Handled by Group: Case Assignment. Steps: Check configs, verify protocols. Priority: critical.\",\"visibility\":\"internal\",\"product_id\":241,\"owner_id\":177}","call_id":"call_Nwr2SYd7MeGlvJVYspf2NK7o","name":"create_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f483860081939c2ae0abbac93c37","status":"completed"},{"call_id":"call_Nwr2SYd7MeGlvJVYspf2NK7o","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"knowledge_id\\\": 370, \\\"kb_number\\\": \\\"KB000370\\\", \\\"title\\\": \\\"Network Resilience Health Check Troubleshooting\\\", \\\"body\\\": \\\"Handled by Group: Case Assignment. Steps: Check configs, verify protocols. Priority: critical.\\\", \\\"state\\\": \\\"published\\\", \\\"visibility\\\": \\\"internal\\\", \\\"product_id\\\": 241, \\\"owner_id\\\": 177, \\\"sys_created_on\\\": \\\"2026-07-24 23:25:56\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:56\\\"}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"case_id\":1233,\"state\":\"in_progress\",\"assignment_group_id\":4,\"priority\":\"critical\",\"escalation\":true,\"escalation_reason\":\"impact\"}","call_id":"call_R3r4HuGBIkrPhYDjrlapt0Kv","name":"update_case","type":"function_call","id":"fc_055f6e21b6fb0470006a63f485d4fc8193917c5e04d01268ff","status":"completed"},{"call_id":"call_R3r4HuGBIkrPhYDjrlapt0Kv","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"case_id\\\": 1233, \\\"number\\\": \\\"CS-0001233\\\", \\\"account_id\\\": 38, \\\"contact_id\\\": 84, \\\"product_id\\\": 241, \\\"installed_product_id\\\": null, \\\"channel\\\": \\\"phone\\\", \\\"priority\\\": \\\"critical\\\", \\\"state\\\": \\\"in_progress\\\", \\\"short_description\\\": \\\"Product: Network Resilience Health Check, Issue: operational instability tied to this service.\\\", \\\"assignment_group_id\\\": 4, \\\"assigned_to\\\": null, \\\"escalation\\\": 1, \\\"escalation_reason\\\": \\\"impact\\\", \\\"reopen_count\\\": 0, \\\"sys_created_on\\\": \\\"2026-07-24 23:25:37\\\", \\\"sys_updated_on\\\": \\\"2026-07-24 23:25:58\\\", \\\"closed_on\\\": null}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"name\":\"SLA Response - Critical\",\"metric\":\"response\",\"applies_to_priority\":\"critical\",\"active\":true}","call_id":"call_HfP7ah2LDJyLToGyBiPNxhJY","name":"find_sla_definitions","type":"function_call","id":"fc_055f6e21b6fb0470006a63f488114c8193adffe11d12e1801f","status":"completed"},{"call_id":"call_HfP7ah2LDJyLToGyBiPNxhJY","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"sla_def_id\\\": 1, \\\"name\\\": \\\"SLA Response - Critical\\\", \\\"metric\\\": \\\"response\\\", \\\"target_mins\\\": 15, \\\"pause_on_pending\\\": 1, \\\"applies_to_priority\\\": \\\"critical\\\", \\\"active\\\": 1, \\\"sys_created_on\\\": \\\"2025-08-27 15:35:03\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"case_id\":1233,\"sla_def_id\":1,\"stage\":\"in_progress\"}","call_id":"call_i7S2ykRnHVzKCrZH0LbQpsZT","name":"link_new_case_sla","type":"function_call","id":"fc_055f6e21b6fb0470006a63f48ae1148193bf67ca73ab238828","status":"completed"},{"call_id":"call_i7S2ykRnHVzKCrZH0LbQpsZT","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"case_sla_id\\\": 2465, \\\"case_id\\\": 1233, \\\"sla_def_id\\\": 1, \\\"stage\\\": \\\"in_progress\\\", \\\"start_time\\\": \\\"2026-07-24 23:26:05\\\", \\\"breach_time\\\": null, \\\"has_breached\\\": 0, \\\"completed_time\\\": null}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"case_id\":1233,\"knowledge_id\":370,\"used_as\":\"suggested\"}","call_id":"call_46WmPfe8FgUTr6fF90aUNooP","name":"link_case_knowledge","type":"function_call","id":"fc_055f6e21b6fb0470006a63f490d6348193b84678158f68d867","status":"completed"},{"call_id":"call_46WmPfe8FgUTr6fF90aUNooP","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"case_kb_id\\\": 528, \\\"case_id\\\": 1233, \\\"knowledge_id\\\": 370, \\\"used_as\\\": \\\"suggested\\\"}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"id":"msg_055f6e21b6fb0470006a63f492be208193aeae2320998101f1","content":[{"annotations":[],"text":"Curtis Mccoy is active and a manager, and he is a member of relevant support groups for handling high-impact responsibilities.\n\nThe new active service \"Network Resilience Health Check\" has been registered.\n\nThe incorrectly opened case CS-0000888 for Stark, Petersen and Palmer has been withdrawn (canceled).\n\nA new phone-reported support case (CS-0001233) related to operational instability tied to the \"Network Resilience Health Check\" service has been created for the same account with critical priority and escalation due to high business risk.\n\nAn internal troubleshooting guide titled \"Network Resilience Health Check Troubleshooting\" has been created for this service.\n\nThe case has been assigned to the \"Case Assignment\" support group, set to in_progress state, escalated with impact reason, and linked to the critical-response SLA for immediate technical action.\n\nThe troubleshooting guide has been linked to the case as a suggested reference.\n\nIf you need any further assistance, please let me know.","type":"output_text","logprobs":[]}],"role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"temperature":0.0,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name.","defer_loading":null},{"name":"find_account","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact account name, e.g., 'Wood and Sons'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.","defer_loading":null},{"name":"list_user_groups","parameters":{"type":"object","properties":{"group_id":{"type":"integer","description":"Filter by unique group identifier."},"name":{"type":"string","description":"Filter by group name (exact match, unique)."},"active":{"type":"boolean","description":"Filter by active status (true = active, false = inactive)."},"type":{"type":"string","enum":["support","backoffice","field","vendor"],"description":"Filter by group type (support, backoffice, field, vendor)."},"created_after":{"type":"string","description":"Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user groups with optional filters.","defer_loading":null},{"name":"list_group_members","parameters":{"type":"object","properties":{"member_id":{"type":"integer","description":"Filter by unique membership identifier."},"group_id":{"type":"integer","description":"Filter by group identifier."},"user_id":{"type":"integer","description":"Filter by user identifier."},"created_after":{"type":"string","description":"Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"List user group members with optional filters. Combination of group_id and user_id is unique.","defer_loading":null},{"name":"find_contacts","parameters":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Unique identifier of the contact."},"account_id":{"type":"integer","description":"ID of the account this contact belongs to."},"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."},"active":{"type":"boolean","description":"Whether the contact is currently active."},"is_primary":{"type":"boolean","description":"True if this is the primary contact for the account."},"created_after":{"type":"string","description":"Filter for contacts created after this timestamp (ISO format)."},"created_before":{"type":"string","description":"Filter for contacts created before this timestamp (ISO format)."}}},"strict":false,"type":"function","description":"Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.","defer_loading":null},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.","defer_loading":null},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.","defer_loading":null},{"name":"search_cases","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case."},"number":{"type":"string","description":"Case number (unique human-readable reference)."},"account_id":{"type":"integer","description":"Filter by account ID. An account represents a business entity or organization."},"contact_id":{"type":"integer","description":"Filter by contact ID."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"installed_product_id":{"type":"integer","description":"Filter by installed product ID. Unique identifier which relates to the installed product table record."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was communicated/created."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"State of the case."},"short_description":{"type":"string","description":"Short description of the case."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation."},"reopen_count":{"type":"integer","description":"Filter by number of times the case was reopened."},"closed_on":{"type":"string","description":"Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."},"created_before":{"type":"string","description":"Return cases created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return cases created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.","defer_loading":null},{"name":"add_new_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Name of the product (e.g., 'Premium Support Package') (unique).","minLength":1},"category":{"type":"string","enum":["software","hardware","service"],"description":"Product category (software, hardware, or service)."},"lifecycle_state":{"type":"string","enum":["active","retired"],"description":"Lifecycle state of the product (active or retired)."},"product_price":{"type":"integer","description":"Price of the product in the smallest currency unit (e.g., cents)."}},"required":["name","category","lifecycle_state"]},"strict":false,"type":"function","description":"Create/register a product. Add product details. Products can be software, hardware, or services offered by the organization.","defer_loading":null},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.","defer_loading":null},{"name":"create_knowledge","parameters":{"type":"object","properties":{"title":{"type":"string","description":"Title of the knowledge article.","minLength":1},"state":{"type":"string","enum":["draft","published","retired"],"description":"Lifecycle state of the article."},"body":{"type":"string","description":"Body of the knowledge article."},"visibility":{"type":"string","enum":["internal","external"],"description":"Who can view the article: internal staff or external customers."},"product_id":{"type":"integer","description":"ID of the related product, if applicable."},"owner_id":{"type":"integer","description":"User ID of the article owner/author."}},"required":["title","state","body","visibility","owner_id"]},"strict":false,"type":"function","description":"Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.","defer_loading":null},{"name":"link_case_knowledge","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case being linked."},"knowledge_id":{"type":"integer","description":"Unique identifier of the knowledge article to link."},"used_as":{"type":"string","enum":["suggested","applied","resolution"],"description":"Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."}},"required":["case_id","knowledge_id","used_as"]},"strict":false,"type":"function","description":"Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.","defer_loading":null}],"top_p":1.0,"background":false,"conversation":null,"max_output_tokens":16384,"max_tool_calls":null,"previous_response_id":null,"prompt":null,"prompt_cache_key":null,"reasoning":{"effort":null,"generate_summary":null,"summary":null,"context":null},"safety_identifier":null,"service_tier":"default","status":"completed","text":{"format":{"type":"text"},"verbosity":"medium"},"top_logprobs":0,"truncation":"disabled","usage":{"input_tokens":185991,"input_tokens_details":{"cached_tokens":0,"audio_tokens":null,"text_tokens":null},"output_tokens":1184,"output_tokens_details":{"reasoning_tokens":0,"text_tokens":null},"total_tokens":187175,"cost":null},"user":null,"store":true,"completed_at":1784935571,"content_filters":[{"blocked":false,"source_type":"completion","content_filter_raw":[],"content_filter_results":{"protected_material_code":{"detected":false,"filtered":false},"protected_material_text":{"detected":false,"filtered":false},"hate":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"start_offset":0,"end_offset":1008,"check_offset":0}}],"frequency_penalty":0.0,"moderation":null,"presence_penalty":0.0,"prompt_cache_retention":"in_memory"},"reward":0.0,"overall_success":false,"verifier_pass_rate":0.6666666666666666,"verification_results":{"Verify New Product":{"passed":true,"expected":1,"actual":1,"comparison_type":"equals","query":"SELECT COUNT(*) AS service_healthy_cnt\nFROM product AS p\nWHERE p.name = 'Network Resilience Health Check'\nAND p.category = 'service'\nAND p.lifecycle_state = 'active';\n","details":"Comparison equals: 1 vs 1"},"Verify Update Case":{"passed":true,"expected":1,"actual":1,"comparison_type":"equals","query":"SELECT COUNT(*) AS case_888_canceled_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 888\nAND cc.state = 'canceled';\n","details":"Comparison equals: 1 vs 1"},"Verify Knowledge Created":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) AS kb_network_resilience_cnt\nFROM knowledge AS k\nWHERE k.title = 'Network Resilience Health Check Troubleshooting'\nAND k.state = 'published'\nAND k.visibility = 'internal'\nAND k.owner_id = 32\nAND k.product_id = 241;\n","details":"Comparison equals: 0 vs 1"},"Verify New Case":{"passed":false,"expected":1,"actual":0,"comparison_type":"equals","query":"SELECT COUNT(*) AS case_network_resilience_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 1233 \nAND cc.account_id = 38\nAND cc.contact_id = 84\nAND cc.product_id = 241\nAND cc.channel = 'phone'\nAND cc.priority = 'critical'\nAND cc.state = 'in_progress'\nAND cc.assignment_group_id = 18\nAND cc.escalation = 1\nAND cc.escalation_reason = 'impact';\n","details":"Comparison equals: 0 vs 1"},"Verify New Case Knowledge Link":{"passed":true,"expected":1,"actual":1,"comparison_type":"equals","query":"SELECT COUNT(*) AS case_1233_kb_370_cnt\nFROM case_knowledge AS ck\nWHERE ck.case_id = 1233\nAND ck.knowledge_id = 370\nAND ck.used_as = 'suggested';\n","details":"Comparison equals: 1 vs 1"},"Verify New Case SLA":{"passed":true,"expected":1,"actual":1,"comparison_type":"equals","query":"SELECT COUNT(*) AS case_1234_sla_cnt\nFROM case_sla AS cs\nWHERE cs.case_id = 1233\nAND cs.sla_def_id = 1\nAND cs.stage = 'in_progress';\n","details":"Comparison equals: 1 vs 1"}},"strict_success":false,"strict_pass_rate":0.6666666666666666,"num_verifiers_defined":6,"num_verifiers_scored":6,"num_tool_calls":22,"tool_latencies_ms":[{"tool":"find_user","gym":"sn-csm-server","latency_ms":11.2},{"tool":"find_account","gym":"sn-csm-server","latency_ms":9.0},{"tool":"list_user_groups","gym":"sn-csm-server","latency_ms":11.2},{"tool":"list_group_members","gym":"sn-csm-server","latency_ms":10.9},{"tool":"list_group_members","gym":"sn-csm-server","latency_ms":12.2},{"tool":"add_new_product","gym":"sn-csm-server","latency_ms":17.9},{"tool":"search_cases","gym":"sn-csm-server","latency_ms":9.5},{"tool":"update_case","gym":"sn-csm-server","latency_ms":16.0},{"tool":"find_contacts","gym":"sn-csm-server","latency_ms":10.5},{"tool":"find_entitlements","gym":"sn-csm-server","latency_ms":11.0},{"tool":"create_new_case","gym":"sn-csm-server","latency_ms":16.9},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":10.0},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":9.8},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":10.0},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":10.4},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":10.1},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":10.3},{"tool":"create_knowledge","gym":"sn-csm-server","latency_ms":20.0},{"tool":"update_case","gym":"sn-csm-server","latency_ms":16.3},{"tool":"find_sla_definitions","gym":"sn-csm-server","latency_ms":10.8},{"tool":"link_new_case_sla","gym":"sn-csm-server","latency_ms":17.6},{"tool":"link_case_knowledge","gym":"sn-csm-server","latency_ms":16.8}],"verifier_metadata":{"task_id":"task_20251210_113549_827_d4a463c3_47b48a98","domain":"csm","mode":"oracle","gym_servers_config":[{"mcp_server_name":"sn-csm-server","mcp_server_url":"http://localhost:8001","seed_database_file":"Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql","context":{"x-user-email":"jose.roberson@servicenow.com"},"user_info":""}],"verifiers":[{"verifier_type":"database_state","name":"Verify New Product","description":"Verify New Product","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS service_healthy_cnt\nFROM product AS p\nWHERE p.name = 'Network Resilience Health Check'\nAND p.category = 'service'\nAND p.lifecycle_state = 'active';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify Update Case","description":"Verify Update Case","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS case_888_canceled_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 888\nAND cc.state = 'canceled';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify Knowledge Created","description":"Verify Knowledge Created","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS kb_network_resilience_cnt\nFROM knowledge AS k\nWHERE k.title = 'Network Resilience Health Check Troubleshooting'\nAND k.state = 'published'\nAND k.visibility = 'internal'\nAND k.owner_id = 32\nAND k.product_id = 241;\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify New Case","description":"Verify New Case","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS case_network_resilience_cnt\nFROM customer_case AS cc\nWHERE cc.case_id = 1233 \nAND cc.account_id = 38\nAND cc.contact_id = 84\nAND cc.product_id = 241\nAND cc.channel = 'phone'\nAND cc.priority = 'critical'\nAND cc.state = 'in_progress'\nAND cc.assignment_group_id = 18\nAND cc.escalation = 1\nAND cc.escalation_reason = 'impact';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify New Case Knowledge Link","description":"Verify New Case Knowledge Link","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS case_1233_kb_370_cnt\nFROM case_knowledge AS ck\nWHERE ck.case_id = 1233\nAND ck.knowledge_id = 370\nAND ck.used_as = 'suggested';\n","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"Verify New Case SLA","description":"Verify New Case SLA","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) AS case_1234_sla_cnt\nFROM case_sla AS cs\nWHERE cs.case_id = 1233\nAND cs.sla_def_id = 1\nAND cs.stage = 'in_progress';\n","expected_value":1,"comparison_type":"equals"}}],"selected_tools":["find_sla_definitions","find_account","link_new_case_sla","find_entitlements","search_cases","list_group_members","create_new_case","find_contacts","update_case","create_knowledge","list_user_groups","link_case_knowledge","find_user","add_new_product"],"restricted_tools":[],"tool_to_gym":{"find_user":"sn-csm-server","find_account":"sn-csm-server","list_user_groups":"sn-csm-server","list_group_members":"sn-csm-server","find_contacts":"sn-csm-server","find_entitlements":"sn-csm-server","find_sla_definitions":"sn-csm-server","search_cases":"sn-csm-server","add_new_product":"sn-csm-server","create_new_case":"sn-csm-server","update_case":"sn-csm-server","link_new_case_sla":"sn-csm-server","create_knowledge":"sn-csm-server","link_case_knowledge":"sn-csm-server"}},"agent_ref":{"name":"enterpriseops_gym_simple_agent"},"_ng_task_index":4,"_ng_rollout_index":0}
+{"responses_create_params":{"background":null,"include":null,"input":[{"content":"CSM Agent Policy\n\nYou are a Customer Service Management Administrator. Your goal is to assist users in the Customer Service Management lifecycle by helping them register cases, validate entitlements, manage customer assets, raise escalations, attach relevant knowledge, close cases, and in other related processes effectively.\n\nYou should always act based on confirmed user context, exising record relationships, and database integrity best practices. Avoid actions that assume data, do not provide enough context, or seem to be in violation of this policy.\n\nGeneral Instructions\n\nBy default, you should assume the roles and responsibilities of an admin to complete a particular request. If a user request violates policy, do not act on it. Perform one operation at a time. Do not provide knowledge or procedures not in the system. Do not ask for any information or confirmation from the user, if you cannot proceed ahead provide the reason for that before pausing.\n\nRoles & Responsibilities\n\nAdministrator\n\nHas full access across all tables. Can create, update, and deactivate: Users, user groups, and group memberships. Accounts, contacts, locations, and entitlements. Products, installed products, SLAs, contracts, and knowledge. Manages assignment rules, workflows, and escalations.\n\nAgent\n\nFrontline support representative handling customer cases. Read-only access to all records (accounts, contacts, products, contracts, entitlements). Can: Create and update customer cases, interactions, and case work notes. Associate knowledge articles with cases. View entitlements and SLAs linked to accounts and cases. Update case assignment, state, and resolution. Cannot modify user, group, or membership data.\n\nManager\n\nSupervises agents and case queues. Has agent privileges plus: Can reassign cases across groups and users. Can escalate cases and override case prioritization. Monitors SLA compliance, case trends, and escalations. Can approve exceptions (e.g., entitlement overrides or escalations). May contribute to knowledge management as reviewers.\n\nCustomer (Portal User)\n\nEnd user accessing the customer portal. Can: View and update their own profile. Create new cases and track the status of their submitted cases. Search and view knowledge articles (based on visibility: internal/external). Participate in community forums (if enabled). Initiate interactions (chat, email, web, etc.). Limited to their own account's data (cannot see other accounts/customers). Cannot access internal system data (users, groups, SLAs, contracts of other customers).\n\nCore Operations\n\nRegistering a Customer Case\n\nBegin by identifying the reporting contact and verifying association with an account. Collect necessary inputs: Issue description (short_description) Product or installed product involved Contact channel (channel) Priority (if not provided → default = moderate) The default case state must be set to new when it is not assigned to any group or user, and must be set to in_progress when it is assigned to a group or user. Verify the product or installed product belongs to the customer's account. Creating an interaction is mandatory whenever a new case is registered.\n\nAssigning a Case\n\nA case may be assigned to: An assignment group (assignment_group_id), or A user (assigned_to) within that group (if not add him to the group). Agents must: Be active, and Be members of the assigned group. Assignment constraints: assigned_to must reference a user with role agent or manager and (if used) member of assignment_group_id.\n\nLinking SLAs to Cases\n\nWhen a newly-created case requires SLA tracking, the case state must first be transitioned from new to in_progress before calling link_new_case_sla. The SLA stage on the linked record should also be set to in_progress so that SLA tracking begins immediately. This applies whenever the request involves applying an SLA, assigning an active owner, or otherwise commencing work on the case.\n\nWorking on a Case\n\nAgents may: Update cause, resolution notes, or other internal fields. Change state (new → in_progress, in_progress → pending/resolved). Attach a missing product or installed product. Link relevant knowledge articles. Important: Cases cannot be closed directly. They must first be moved to resolved, then to closed. If a case is invalid, it may be canceled.\n\nCase Lifecycle Management\n\nValid state transitions: new → in_progress / pending / resolved in_progress → pending / resolved pending → in_progress / resolved resolved → closed / new canceled At each step: Validate acting user's relationship to the case. Capture timestamps (sys_updated_on, closed_on where applicable). Prevent premature closure without resolution. When a resolved issue occurs again, the closed case can be reopened by setting the state to new, increasing the reopen_count by 1, and clearing the closed_on timestamp.\n\nEntitlement Validation\n\nBefore applying entitlement: Check it is active and within contract validity. Product-specific entitlements must match the case product (unless entitlement is account-wide). max_cases_per_month = 0 means unlimited; otherwise enforce limits. If entitlement is invalid → inform the user.\n\nInstalled Product Management\n\nInstalled products must: Be active / in_use. Belong to the reporting account. Do not attach items in retired / repair status to new cases. Ensure installed product's product matches the case product.\n\nLinking Knowledge Articles\n\nWhen linking knowledge: Articles must be in state = published. Visibility rules apply: internal = agents only external = customers can view Link articles to cases via case_knowledge (usage = suggested, applied, resolution). Ownership is tracked via owner_id.\n\nEscalations\n\nEscalations may be raised when: SLA breach risk exists, or Customer explicitly requests escalation, or High business risk/impact. Steps: Record escalation = true on case. Capture escalation_reason. Ensure justification is logged in case notes. There is no separate escalation record. Escalation is tracked within the case.\n\nProduct Handling\n\nProducts must be: Present in product table, In lifecycle_state = active. Installed products must match the product and account context.\n\nSecurity\n\nUsers may only view or update cases they own, are assigned to, or are in the assigned group. Do not disclose personal data or case details outside these permissions.\n\nValidation, Error Handling & Logging\n\nAlways validate existence and integrity of: Users, accounts, contacts, products, entitlements, and cases. State transitions follow lifecycle rules. All actions must: Update sys_updated_on. Capture timestamps (e.g., closed_on for case closure).\n\nService Levels & Timelines\n\nCase handling Response and resolution timelines are determined by the entitlements (entitlement table) linked to the customer account and product. Applicable SLAs (sla_definition and case_sla tables) set the exact targets for response or resolution, and may vary by case priority, support level, and coverage hours. SLA pause behavior: Obey sla_definition.pause_on_pending; when case state is pending, pause applicable SLAs. If no entitlement or SLA is associated with the account/product, no service level commitments are in scope. Installed product repair / replacement Commitments depend on warranty contracts or support agreements (contract table). The applicable SLA target will be enforced only if defined under the customer's entitlement. In absence of a valid contract or entitlement, no guaranteed turnaround applies. Knowledge article publication / retirement Service levels for publishing or retiring knowledge are governed by internal operational policies and are not bound by customer-facing SLAs. Unless explicitly defined in entitlements or SLAs, no service level commitments are in scope. User & group management (administrative actions) Internal administrative tasks (user/group creation, role updates, membership changes) are not subject to customer-facing SLAs. Unless an internal SLA is defined, no service level commitments are in scope.\n\nPredefined Lists (Enumerations)\n\nOnly the following values are allowed for these fields:\n\nUsers & Groups user.role: admin, agent, manager, customer user_group.type: support, backoffice, field, vendor\n\nGeography location.city: new_york, london, mumbai, tokyo, sydney location.country: usa, uk, india, japan, australia\n\nAccounts & Contacts account.account_type: customer, partner, internal\n\nProducts & Installed Base product.category: software, hardware, service product.lifecycle_state: active, retired installed_product.status: in_use, in_stock, repair, retired\n\nContracts, Entitlements, SLAs contract.contract_type: support, warranty, subscription contract.status: active, suspended, expired entitlement.support_level: standard, premium, enterprise entitlement.coverage_hours: h8x5, h12x6, h24x7 sla_definition.metric: response, resolution sla_definition.applies_to_priority: critical, high, moderate, low\n\nCase Management customer_case.channel: web, email, phone, chat, social, alert, community customer_case.priority: critical, high, moderate, low customer_case.state: new, in_progress, pending, resolved, closed, canceled customer_case.escalation_reason: urgency, vip, impact, breach_risk, customer_request\n\nInteractions & Knowledge interaction.channel: web, email, phone, chat, social, alert, community knowledge.state: draft, published, retired knowledge.visibility: internal, external case_knowledge.used_as: suggested, applied, resolution Enforcement: reject any value outside the list with INVALID_ENUM_VALUE.\n\nKnowledge Related Policies: When a new case is created and is asked to be investigated, then a knowledge base search should be performed. For all cases the entitlement for the product should be verified and should be actively running. If no relevant knowledge is found and case is being closed, a new knowledge article should be created to capture the findings and resolution steps. If a knowledge article is created, it should be linked to the case for future reference. When new case moves to work in progress appropriate SLA should be aligned to it. Used as for knowledge base to case: When the knowledge is found through automated search it should be linked as suggested. If the knowledge is found to be useful to resolve the case or is being created after case resolution it should have used as type to resolution in linking. In other cases if knowledge is linked it should as applied. If knowledge article is found then it should be used to assist in the next set of actions. For example, it might details regarding product configuration, troubleshooting steps, or best practices or team that should work on it.\n\nWhen an employee leaves, deactivate their account, and remove them from their group.\n\nFree form text policies: (For texts like short description of cases, title of knowledge, escalation reason and content/body of knowledge) Character limits: 30–120 chars Case Short Description: It can be something like: \"Product: \" + Product name + \", Issue: is not working as expected.\" KB title: Issue Resolution related to , step-by-step guide KB content/body: This kind of issues are tackled by Assignment Group: , Assigned to: . Steps to resolve the issue: , Suggested Priority: . Escalation reason: The case could not be completed on time/exceeds the time limit or has priority beyond the defined list of priorities.","role":"system","type":"message"},{"content":"Marc Henry needs to address a critical situation for Stark Industries. Update the existing entitlement for their Palo Alto Networks PA-3220 Variant 8 to our highest Enterprise support level, ensuring 24x7 coverage and removing any monthly case limits. Register a new critical case for this device, reporting that the Dataplane crashes repeatedly, using the phone channel. Assign the case to Curtis McCoy and the Escalation Management group. Ensure the mandatory Resolution SLA is applied to this case.","role":"user","type":"message"}],"instructions":null,"max_output_tokens":16384,"max_tool_calls":null,"metadata":null,"model":null,"parallel_tool_calls":true,"previous_response_id":null,"prompt":null,"reasoning":null,"service_tier":null,"store":null,"temperature":0.0,"text":null,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name."},{"name":"find_contact_by_portal_user","parameters":{"type":"object","properties":{"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}},"required":["portal_user_id"]},"strict":false,"type":"function","description":"Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table."},{"name":"find_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Product name, e.g., 'Pulse Edge'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Look up a product by its exact name. Product represents an item or service offered by the company."},{"name":"find_user_group","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact name of the user group (unique).","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes."},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts."},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement."},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority."},{"name":"update_entitlement","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique ID of the entitlement to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"product_id":{"type":"integer","description":"Update the product ID linked to the entitlement."},"contract_id":{"type":"integer","description":"Update the contract ID linked to the entitlement."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Update the support level."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Update the coverage hours."},"max_cases_per_month":{"type":"integer","description":"Update the maximum number of support cases per month."},"active":{"type":"boolean","description":"Set entitlement status as active (true) or inactive (false)."}},"required":["entitlement_id"]},"strict":false,"type":"function","description":"Update an entitlement (partial updates allowed). Entitlements define the support and service levels provided to an account for specific products or contracts."},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved."},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case."}],"top_logprobs":null,"top_p":null,"truncation":null,"user":null,"stream":null},"response":{"id":"resp_ztf6j7l-VCH4gpuYJFDZFQHFWEB3jdGuTeYt4wOzv0VeDdhxR9itnnIHwYmSDDK7CTqtwmBhjMCON9T2U8eYmqZC4OTbQ5OoDKUgoncYh1GXyicoc2Xp-xHfF1pOa8EAtgOBXIw8fNOZ7KQwZ2JCy9OEXx-ppPKFw-P6suLBgsfWo5BwqOyCtK7rZxrLmpwfM6td0UipkIhjfYb18St7xG8ceU27XZjAXBQv2HQaJcJKPk5ZeuxWuicje07BDucMl8MpPWM3hnUjtwpgKpM1nqsjJondcFcsINrzJ5EQ5mtWOzBJBisg3Q1ooIvXPzexFVEjqrop1cIHHoTpKvfxQFe6LKg1hIvha6GJYkL1R97efjkpMTmdQPKPDOxMdQk6r5ZsZJKbdku6se96Sss=","created_at":1784935831.0,"error":null,"incomplete_details":null,"instructions":null,"metadata":{},"model":"azure/openai/gpt-4.1-mini","object":"response","output":[{"arguments":"{\"name\":\"Marc Henry\"}","call_id":"call_06P5QqvdQZlHwKk4QK4D5yLz","name":"find_user","type":"function_call","id":"fc_01f0c80d1be1558e006a63f463d7ac8190bf7467672c7487c0","status":"completed"},{"arguments":"{\"name\":\"Curtis McCoy\"}","call_id":"call_VFtBTmHHXyJyyfiD2vXSHS48","name":"find_user","type":"function_call","id":"fc_01f0c80d1be1558e006a63f463d7c88190ab55763b90e36dd1","status":"completed"},{"arguments":"{\"name\":\"Escalation Management\"}","call_id":"call_5EushxfkHiGHu5PUpniOUL2R","name":"find_user_group","type":"function_call","id":"fc_01f0c80d1be1558e006a63f463d7d8819098d94a4282681c55","status":"completed"},{"arguments":"{\"name\":\"Palo Alto Networks PA-3220 Variant 8\"}","call_id":"call_80l2ov9EIElINExpUoRnjeOk","name":"find_product","type":"function_call","id":"fc_01f0c80d1be1558e006a63f463d7e881908b82b7b9d9db2094","status":"completed"},{"call_id":"call_06P5QqvdQZlHwKk4QK4D5yLz","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"user_id\\\": 20, \\\"first_name\\\": \\\"Marc\\\", \\\"last_name\\\": \\\"Henry\\\", \\\"email\\\": \\\"marc.henry@stark-industries.com\\\", \\\"role\\\": \\\"customer\\\", \\\"location_id\\\": 20, \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_VFtBTmHHXyJyyfiD2vXSHS48","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"user_id\\\": 177, \\\"first_name\\\": \\\"Curtis\\\", \\\"last_name\\\": \\\"Mccoy\\\", \\\"email\\\": \\\"curtis.mccoy@servicenow.com\\\", \\\"role\\\": \\\"manager\\\", \\\"location_id\\\": 177, \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_5EushxfkHiGHu5PUpniOUL2R","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"group_id\\\": 18, \\\"name\\\": \\\"Escalation Management\\\", \\\"type\\\": \\\"support\\\", \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"call_id":"call_80l2ov9EIElINExpUoRnjeOk","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"product_id\\\": 140, \\\"name\\\": \\\"Palo Alto Networks PA-3220 Variant 8\\\", \\\"category\\\": \\\"hardware\\\", \\\"lifecycle_state\\\": \\\"active\\\"}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"product_id\":140,\"status\":\"in_use\"}","call_id":"call_yQUpMckflLQvA8lUM3aSWGZp","name":"retrieve_installed_products","type":"function_call","id":"fc_01f0c80d1be1558e006a63f46584b88190b97717897a809dd6","status":"completed"},{"call_id":"call_yQUpMckflLQvA8lUM3aSWGZp","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[{\\\"installed_product_id\\\": 42, \\\"account_id\\\": 8, \\\"product_id\\\": 140, \\\"location_id\\\": 817, \\\"serial_number\\\": \\\"P140-898548-8853\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2026-12-20\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:35:51\\\"}, {\\\"installed_product_id\\\": 113, \\\"account_id\\\": 21, \\\"product_id\\\": 140, \\\"location_id\\\": 843, \\\"serial_number\\\": \\\"P140-709063-5330\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2029-04-08\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:49:49\\\"}, {\\\"installed_product_id\\\": 182, \\\"account_id\\\": 33, \\\"product_id\\\": 140, \\\"location_id\\\": 867, \\\"serial_number\\\": \\\"P140-411674-6934\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2027-09-16\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:40:47\\\"}, {\\\"installed_product_id\\\": 243, \\\"account_id\\\": 44, \\\"product_id\\\": 140, \\\"location_id\\\": 890, \\\"serial_number\\\": \\\"P140-690917-4065\\\", \\\"status\\\": \\\"in_use\\\", \\\"warranty_end\\\": \\\"2028-03-14\\\", \\\"sys_created_on\\\": \\\"2025-08-27 15:41:50\\\"}]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"account_id\":44,\"product_id\":140,\"active\":true}","call_id":"call_aEPyeuI1Sb4cMq2pTZl2Cvwz","name":"find_entitlements","type":"function_call","id":"fc_01f0c80d1be1558e006a63f594331c8190bdfa2ba0b860a962","status":"completed"},{"call_id":"call_aEPyeuI1Sb4cMq2pTZl2Cvwz","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"[]\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"arguments":"{\"portal_user_id\":20}","call_id":"call_G0MPfEW5IxOLxag785FwMUkb","name":"find_contact_by_portal_user","type":"function_call","id":"fc_01f0c80d1be1558e006a63f5965dac8190a252d0f28d8a0b7c","status":"completed"},{"call_id":"call_G0MPfEW5IxOLxag785FwMUkb","output":"{\"meta\": null, \"content\": [{\"type\": \"text\", \"text\": \"{\\\"contact_id\\\": 10, \\\"account_id\\\": 8, \\\"portal_user_id\\\": 20, \\\"active\\\": 1}\", \"annotations\": null, \"meta\": null}], \"structuredContent\": null, \"isError\": false}","type":"function_call_output","id":null,"status":null},{"id":"msg_01f0c80d1be1558e006a63f5982d0481908afbcf920e99785b","content":[{"annotations":[],"text":"The installed product \"Palo Alto Networks PA-3220 Variant 8\" with serial number P140-690917-4065 belongs to account ID 44, but the contact Marc Henry is associated with account ID 8. There is no active entitlement found for account ID 44 and this product.\n\nPlease confirm if the entitlement update and case registration should be done for account ID 44 or account ID 8. Also, please confirm the installed product serial number to be used for the case.","type":"output_text","logprobs":[]}],"role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"temperature":0.0,"tool_choice":"auto","tools":[{"name":"find_user","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Full name of user, e.g., 'Harry Middleton'."}},"required":["name"]},"strict":false,"type":"function","description":"Look up a user (portal customer, portal user or internal agent) by full name.","defer_loading":null},{"name":"find_contact_by_portal_user","parameters":{"type":"object","properties":{"portal_user_id":{"type":"integer","description":"Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."}},"required":["portal_user_id"]},"strict":false,"type":"function","description":"Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.","defer_loading":null},{"name":"find_product","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Product name, e.g., 'Pulse Edge'.","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Look up a product by its exact name. Product represents an item or service offered by the company.","defer_loading":null},{"name":"find_user_group","parameters":{"type":"object","properties":{"name":{"type":"string","description":"Exact name of the user group (unique).","minLength":1}},"required":["name"]},"strict":false,"type":"function","description":"Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.","defer_loading":null},{"name":"retrieve_installed_products","parameters":{"type":"object","properties":{"installed_product_id":{"type":"integer","description":"Unique installed product ID."},"location_id":{"type":"integer","description":"Filter by location/site ID. Unique identifier which relates to the location table record."},"account_id":{"type":"integer","description":"Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter by product ID. Unique identifier which relates to the product table record."},"serial_number":{"type":"string","description":"Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."},"status":{"type":"string","enum":["in_use","in_stock","repair","retired"],"description":"Current status of the installed product."},"warranty_end":{"type":"string","description":"Exact warranty end date (YYYY-MM-DD)."},"created_before":{"type":"string","description":"Return products created before this date (YYYY-MM-DD HH:MM:SS)."},"created_after":{"type":"string","description":"Return products created after this date (YYYY-MM-DD HH:MM:SS)."}}},"strict":false,"type":"function","description":"Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.","defer_loading":null},{"name":"find_entitlements","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique identifier of the entitlement."},"account_id":{"type":"integer","description":"Filter entitlements by associated account ID. An account represents a business entity or organization."},"product_id":{"type":"integer","description":"Filter entitlements by product ID. Unique identifier which relates to the product table record."},"contract_id":{"type":"integer","description":"Filter entitlements by contract ID. Unique identifier which relates to the contract table record."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Support level associated with the entitlement."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."},"max_cases_per_month":{"type":"integer","description":"Maximum number of support cases allowed per month under this entitlement."},"active":{"type":"boolean","description":"Filter by entitlement status (true = active, false = inactive)."},"created_before":{"type":"string","description":"Return entitlements created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return entitlements created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.","defer_loading":null},{"name":"find_sla_definitions","parameters":{"type":"object","properties":{"sla_def_id":{"type":"integer","description":"Unique identifier of the SLA definition."},"name":{"type":"string","description":"Name of the SLA definition (e.g., 'SLA Response - Critical').","minLength":1},"metric":{"type":"string","enum":["response","resolution"],"description":"SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."},"target_mins":{"type":"integer","description":"Target duration for the SLA in minutes."},"pause_on_pending":{"type":"boolean","description":"Whether the SLA timer pauses when the case is in a pending state."},"applies_to_priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level this SLA definition applies to."},"active":{"type":"boolean","description":"Whether the SLA definition is active (true) or inactive (false)."},"created_before":{"type":"string","description":"Return SLA definitions created before this date (YYYY-MM-DD format)."},"created_after":{"type":"string","description":"Return SLA definitions created after this date (YYYY-MM-DD format)."}}},"strict":false,"type":"function","description":"Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.","defer_loading":null},{"name":"update_entitlement","parameters":{"type":"object","properties":{"entitlement_id":{"type":"integer","description":"Unique ID of the entitlement to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"product_id":{"type":"integer","description":"Update the product ID linked to the entitlement."},"contract_id":{"type":"integer","description":"Update the contract ID linked to the entitlement."},"support_level":{"type":"string","enum":["standard","premium","enterprise"],"description":"Update the support level."},"coverage_hours":{"type":"string","enum":["h8x5","h12x6","h24x7"],"description":"Update the coverage hours."},"max_cases_per_month":{"type":"integer","description":"Update the maximum number of support cases per month."},"active":{"type":"boolean","description":"Set entitlement status as active (true) or inactive (false)."}},"required":["entitlement_id"]},"strict":false,"type":"function","description":"Update an entitlement (partial updates allowed). Entitlements define the support and service levels provided to an account for specific products or contracts.","defer_loading":null},{"name":"create_new_case","parameters":{"type":"object","properties":{"account_id":{"type":"integer","description":"Account ID associated with the case."},"contact_id":{"type":"integer","description":"Contact ID who raised the case."},"product_id":{"type":"integer","description":"Product ID related to the case."},"installed_product_id":{"type":"integer","description":"Installed product ID associated with the case."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Channel through which the case was raised."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Priority level of the case."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Initial state of the case."},"short_description":{"type":"string","minLength":1,"maxLength":500,"description":"Short description summarizing the case issue."},"escalation":{"type":"boolean","description":"Whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Reason for escalation if applicable.","minLength":1},"reopen_count":{"type":"integer","description":"Initial reopen count for the case."},"closed_on":{"type":"string","description":"Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Assignment group ID responsible for the case."},"assigned_to":{"type":"integer","description":"User ID assigned to the case."}},"required":["account_id","contact_id","channel","priority","state","short_description"]},"strict":false,"type":"function","description":"Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"update_case","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"Unique identifier of the case to update."},"account_id":{"type":"integer","description":"Update the associated account ID."},"contact_id":{"type":"integer","description":"Update the associated contact ID."},"product_id":{"type":"integer","description":"Update the product ID associated with the case."},"installed_product_id":{"type":"integer","description":"Update the installed product ID."},"channel":{"type":"string","enum":["web","email","phone","chat","social","alert","community"],"description":"Update the channel used to create the case."},"priority":{"type":"string","enum":["critical","high","moderate","low"],"description":"Update the case priority."},"state":{"type":"string","enum":["new","in_progress","pending","resolved","closed","canceled"],"description":"Update the case state."},"short_description":{"type":"string","description":"Update the case short description.","minLength":1,"maxLength":500},"escalation":{"type":"boolean","description":"Update whether the case is escalated."},"escalation_reason":{"type":"string","enum":["urgency","vip","impact","breach_risk","customer_request"],"description":"Update the escalation reason.","minLength":1},"reopen_count":{"type":"integer","description":"Update the reopen count."},"closed_on":{"type":"string","description":"Update the closed date (YYYY-MM-DD HH:MM:SS)."},"assignment_group_id":{"type":"integer","description":"Update the assignment group ID."},"assigned_to":{"type":"integer","description":"Update the assigned user ID."}},"required":["case_id"]},"strict":false,"type":"function","description":"Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.","defer_loading":null},{"name":"link_new_case_sla","parameters":{"type":"object","properties":{"case_id":{"type":"integer","description":"ID of the case being linked to an SLA."},"sla_def_id":{"type":"integer","description":"ID of the SLA definition to apply."},"stage":{"type":"string","enum":["in_progress","paused","completed","canceled"],"description":"Initial stage of SLA tracking."},"start_time":{"type":"string","description":"Start time of SLA tracking. If omitted, defaults to current timestamp."},"breach_time":{"type":"string","description":"Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."},"has_breached":{"type":"boolean","description":"Whether the SLA was already breached at creation (true/false)."},"completed_time":{"type":"string","description":"Completion timestamp if the SLA is already completed."}},"required":["case_id","sla_def_id","stage"]},"strict":false,"type":"function","description":"Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.","defer_loading":null}],"top_p":1.0,"background":false,"conversation":null,"max_output_tokens":16384,"max_tool_calls":null,"previous_response_id":null,"prompt":null,"prompt_cache_key":null,"reasoning":{"effort":null,"generate_summary":null,"summary":null,"context":null},"safety_identifier":null,"service_tier":"default","status":"completed","text":{"format":{"type":"text"},"verbosity":"medium"},"top_logprobs":0,"truncation":"disabled","usage":{"input_tokens":24776,"input_tokens_details":{"cached_tokens":0,"audio_tokens":null,"text_tokens":null},"output_tokens":264,"output_tokens_details":{"reasoning_tokens":0,"text_tokens":null},"total_tokens":25040,"cost":null},"user":null,"store":true,"completed_at":1784935832,"content_filters":[{"blocked":false,"source_type":"completion","content_filter_raw":[],"content_filter_results":{"protected_material_code":{"detected":false,"filtered":false},"protected_material_text":{"detected":false,"filtered":false},"hate":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"start_offset":0,"end_offset":451,"check_offset":0}}],"frequency_penalty":0.0,"moderation":null,"presence_penalty":0.0,"prompt_cache_retention":"in_memory"},"reward":0.0,"overall_success":false,"verifier_pass_rate":0.0,"verification_results":{"update_entitlement":{"passed":false,"expected":"enterprise","actual":"standard","comparison_type":"equals","query":"SELECT support_level FROM entitlement WHERE entitlement_id = 73;","details":"Comparison equals: standard vs enterprise"},"create_new_case":{"passed":false,"expected":"in_progress","actual":[],"comparison_type":"equals","query":"SELECT state FROM customer_case WHERE case_id = 1233;","details":"Comparison equals: [] vs in_progress"},"link_new_case_sla":{"passed":false,"expected":"in_progress","actual":[],"comparison_type":"equals","query":"SELECT stage FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;","details":"Comparison equals: [] vs in_progress"}},"strict_success":false,"strict_pass_rate":0.09090909090909091,"num_verifiers_defined":11,"num_verifiers_scored":3,"num_tool_calls":7,"tool_latencies_ms":[{"tool":"find_user","gym":"sn-csm-server","latency_ms":9.2},{"tool":"find_user","gym":"sn-csm-server","latency_ms":9.4},{"tool":"find_user_group","gym":"sn-csm-server","latency_ms":8.2},{"tool":"find_product","gym":"sn-csm-server","latency_ms":14.4},{"tool":"retrieve_installed_products","gym":"sn-csm-server","latency_ms":10.0},{"tool":"find_entitlements","gym":"sn-csm-server","latency_ms":11.2},{"tool":"find_contact_by_portal_user","gym":"sn-csm-server","latency_ms":10.6}],"verifier_metadata":{"task_id":"task_20251205_153330_906_a8eea1c0_8c7a6205","domain":"csm","mode":"oracle","gym_servers_config":[{"mcp_server_name":"sn-csm-server","mcp_server_url":"http://localhost:8001","seed_database_file":"Domain Wise DBs and Task-DB Mappings/csm/dbs/db_1762254390925_u5icw4thh.sql","context":{"x-user-email":"joanne.simpson@servicenow.com"},"user_info":""}],"verifiers":[{"verifier_type":"database_state","name":"update_entitlement","description":"Verify Entitlement 73's coverage hours were updated to h24x7.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;","expected_value":"h24x7","comparison_type":"equals"}},{"verifier_type":"database_state","name":"update_entitlement","description":"Verify Entitlement 73's max case limit was set to unlimited (0).","gym_name":"sn-csm-server","validation_config":{"query":"SELECT max_cases_per_month FROM entitlement WHERE entitlement_id = 73;","expected_value":0,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"update_entitlement","description":"Verify that Entitlement 73's update timestamp is newer than its original data record to confirm the update occurred.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM entitlement WHERE entitlement_id = 73 AND sys_updated_on IS NOT NULL","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"create_new_case","description":"Verify the new case (ID 1233) was created for the correct installed product (ID 42).","gym_name":"sn-csm-server","validation_config":{"query":"SELECT installed_product_id FROM customer_case WHERE case_id = 1233;","expected_value":42,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"create_new_case","description":"Verify the new case priority is 'critical' and channel is 'phone'.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT priority FROM customer_case WHERE case_id = 1233 AND channel = 'phone';","expected_value":"critical","comparison_type":"equals"}},{"verifier_type":"database_state","name":"create_new_case","description":"Verify the case (ID 1233) was correctly assigned to the Escalation Management group (ID 18).","gym_name":"sn-csm-server","validation_config":{"query":"SELECT assignment_group_id FROM customer_case WHERE case_id = 1233;","expected_value":18,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"create_new_case","description":"Verify the case (ID 1233) was correctly assigned to Curtis McCoy (ID 177).","gym_name":"sn-csm-server","validation_config":{"query":"SELECT assigned_to FROM customer_case WHERE case_id = 1233;","expected_value":177,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"create_new_case","description":"Verify the case initial state was correctly set to 'in_progress'.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT state FROM customer_case WHERE case_id = 1233;","expected_value":"in_progress","comparison_type":"equals"}},{"verifier_type":"database_state","name":"link_new_case_sla","description":"Verify that the Critical Resolution SLA (ID 6) was linked to the new case (ID 1233).","gym_name":"sn-csm-server","validation_config":{"query":"SELECT COUNT(*) FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;","expected_value":1,"comparison_type":"equals"}},{"verifier_type":"database_state","name":"link_new_case_sla","description":"Verify that the new case_sla entry's stage is set to 'in_progress'.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT stage FROM case_sla WHERE case_id = 1233 AND sla_def_id = 6;","expected_value":"in_progress","comparison_type":"equals"}},{"verifier_type":"database_state","name":"update_entitlement","description":"Verify Entitlement 73's support level was updated to enterprise.","gym_name":"sn-csm-server","validation_config":{"query":"SELECT support_level FROM entitlement WHERE entitlement_id = 73;","expected_value":"enterprise","comparison_type":"equals"}}],"selected_tools":["find_user_group","retrieve_installed_products","update_case","update_entitlement","find_contact_by_portal_user","find_sla_definitions","find_entitlements","find_user","find_product","link_new_case_sla","create_new_case"],"restricted_tools":[],"tool_to_gym":{"find_user":"sn-csm-server","find_contact_by_portal_user":"sn-csm-server","find_product":"sn-csm-server","find_user_group":"sn-csm-server","retrieve_installed_products":"sn-csm-server","find_entitlements":"sn-csm-server","find_sla_definitions":"sn-csm-server","update_entitlement":"sn-csm-server","create_new_case":"sn-csm-server","update_case":"sn-csm-server","link_new_case_sla":"sn-csm-server"}},"agent_ref":{"name":"enterpriseops_gym_simple_agent"},"_ng_task_index":0,"_ng_rollout_index":0}
diff --git a/resources_servers/enterpriseops_gym/data/hybrid_synthetic.jsonl b/resources_servers/enterpriseops_gym/data/hybrid_synthetic.jsonl
new file mode 100644
index 0000000000..6c77958910
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/hybrid_synthetic.jsonl
@@ -0,0 +1 @@
+{"responses_create_params": {"input": [{"role": "system", "content": "You are an enterprise operations assistant with access to Microsoft Teams and Email administration tools. Complete the user's request precisely using the available tools. Perform one operation at a time. Do not ask for confirmation."}, {"role": "user", "content": "Two things please: (1) In Microsoft Teams, create a new channel named 'Phase 3 Integration Updates' in the TechCorp Solutions Team (team ID: team_techcorp_001). (2) In the email system, create a label named 'Phase3-Integration' for the user with ID user_001 (alice@example.com)."}], "tools": [{"type": "function", "name": "create_channel", "description": "Create a new channel in a team. API Endpoint: POST /teams/{team-id}/channels", "parameters": {"type": "object", "properties": {"teamId": {"type": "string", "description": "Unique team identifier where the channel will be created"}, "displayName": {"type": "string", "description": "Channel display name", "maxLength": 50, "minLength": 1}, "description": {"type": "string", "description": "Channel description (optional)", "maxLength": 1024}, "membershipType": {"type": "string", "enum": ["standard", "private", "shared"], "description": "Channel membership type", "default": "standard"}, "members": {"type": "array", "description": "Initial channel members (required for private/shared channels)", "items": {"type": "object", "properties": {"user_odata_bind": {"type": "string", "description": "OData bind URL for user reference (e.g., https://graph.microsoft.com/v1.0/users/{user-id})"}, "roles": {"type": "array", "items": {"type": "string", "enum": ["owner", "member", "guest"]}, "description": "Roles assigned to the user. Per Microsoft Graph API: 'owner' for owner privileges, 'guest' for in-tenant guest users, empty array for basic members. Out-of-tenant external members are assigned 'owner' role.", "default": ["member"]}, "displayName": {"type": "string", "description": "Display name of the user"}, "email": {"type": "string", "description": "Email address of the user"}}, "required": ["user_odata_bind"]}}, "isFavoriteByDefault": {"type": "boolean", "description": "Whether channel is favorite by default", "default": false}, "_microsoft_graph_channelCreationMode": {"type": "string", "enum": ["migration"], "description": "Special creation mode for data migration. When specified, createdDateTime can be provided."}}, "required": ["teamId", "displayName"]}, "strict": false}, {"type": "function", "name": "list_channels", "description": "Retrieve the list of channels in a team (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/channels\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | Channel.ReadBasic.All | ChannelSettings.Read.All, ChannelSettings.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | ChannelSettings.Read.Group | Channel.ReadBasic.All, ChannelSettings.Read.All, ChannelSettings.ReadWrite.All, ChannelSettings.ReadWrite.Group, Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n\n Important Access Control:\n - Only team members can access channels (enforced by team membership verification)\n - Guest users can't see private or shared channels they aren't members of\n - Unicode characters in parameters are sanitized to prevent encoding errors\n\n Query Parameters Support:\n - _filter: Supports 'membershipType eq private', 'membershipType eq shared', 'membershipType eq standard'\n - _select: Exclude email property for better performance (recommended by Microsoft Graph API)\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ", "parameters": {"type": "object", "properties": {"teamId": {"type": "string", "description": "Unique team identifier (must be a team where the user is a member)"}, "_filter": {"type": "string", "description": "OData filter expression. Examples: 'membershipType eq \\'private\\'', 'membershipType eq \\'shared\\'', 'membershipType eq \\'standard\\''", "examples": ["membershipType eq 'private'", "membershipType eq 'shared'", "membershipType eq 'standard'"]}, "_select": {"type": "string", "description": "Comma-separated list of properties to return for performance optimization. Recommended to exclude 'email' property per Microsoft Graph API guidance.", "examples": ["displayName,description,membershipType", "id,displayName,isArchived"]}}, "required": ["teamId"]}, "strict": false}, {"type": "function", "name": "create_label", "description": "Creates a new label", "parameters": {"type": "object", "properties": {"userId": {"type": "string", "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.", "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"}, "name": {"type": "string", "description": "The display name of the label"}, "messageListVisibility": {"type": "string", "enum": ["show", "hide"], "description": "The visibility of messages with this label in the message list", "default": "show"}, "labelListVisibility": {"type": "string", "enum": ["labelShow", "labelShowIfUnread", "labelHide"], "description": "The visibility of the label in the label list", "default": "labelShow"}, "color": {"type": "object", "description": "Color settings for the label (user labels only)", "properties": {"textColor": {"type": "string", "description": "The text color of the label, represented as hex string. This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"}, "backgroundColor": {"type": "string", "description": "The background color represented as hex string #RRGGBB (ex #000000). This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"}}}}, "required": ["name", "userId"]}, "strict": false}, {"type": "function", "name": "list_labels", "description": "Lists all labels in the user's mailbox", "parameters": {"type": "object", "properties": {"userId": {"type": "string", "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.", "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"}}, "required": ["userId"]}, "strict": false}]}, "verifier_metadata": {"task_id": "hybrid_synthetic_channel_label", "domain": "hybrid", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "gym-teams-mcp", "mcp_server_url": "http://localhost:8002", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/teams/dbs/db_1763033448404_zhkq3s7ut.sql", "context": {}}, {"mcp_server_name": "gym-email-mcp", "mcp_server_url": "http://localhost:8004", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/email/dbs/db_1763188937209_paq12p3yu.sql", "context": {}}], "verifiers": [{"verifier_type": "database_state", "name": "create_channel", "description": "Channel created in the teams gym", "gym_name": "gym-teams-mcp", "validation_config": {"query": "SELECT COUNT(*) FROM channels WHERE display_name = 'Phase 3 Integration Updates';", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "create_label", "description": "Label created for alice in the email gym", "gym_name": "gym-email-mcp", "validation_config": {"query": "SELECT COUNT(*) FROM labels WHERE name = 'Phase3-Integration' AND user_id = 'user_001';", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["get_team", "create_channel", "list_channels", "create_label", "list_labels"], "restricted_tools": [], "tool_to_gym": {"create_channel": "gym-teams-mcp", "list_channels": "gym-teams-mcp", "create_label": "gym-email-mcp", "list_labels": "gym-email-mcp"}}}
diff --git a/resources_servers/enterpriseops_gym/data/itsm_revised.jsonl b/resources_servers/enterpriseops_gym/data/itsm_revised.jsonl
new file mode 100644
index 0000000000..65d96f7a16
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/itsm_revised.jsonl
@@ -0,0 +1 @@
+{"responses_create_params": {"input": [{"role": "system", "content": "# **ITSM Assistant Policy**\n\n**Role:** ITSM Assistant (IT Service Management)\n\n**Mandate:** Ensure the efficient, secure, and controlled delivery of IT services by managing the full lifecycle of Incidents, Service Requests, Changes, Problems, and Configuration Items (CIs) in strict accordance with defined policies and best practices.\n\nFirst you must check the user information and operate exclusively based on **confirmed user roles**, **verified record relationships**, and **ITIL/database integrity rules**. You are strictly prohibited from assuming data, executing ambiguous commands, bypassing mandatory approvals, or violating audit and compliance requirements.\n\n---\n\n## **1. General Operational Instructions and Constraints**\n\n* **Policy Violation:** If a user request violates any rule herein, you **must halt the operation** and provide the specific policy reason before pausing.\n\n* **Atomic Operations:** Perform **one validated operation at a time**, except when using approved batch endpoints. Do not allow a request to proceed if it requires data that is missing or the current record state prevents the action.\n\n* **Knowledge Scope:** Do not disclose information that is outside the authenticated user's access scope.\n\n* **User Clarification:** Do not ask for further information. If the request is ambiguous, return the list and state the ambiguity. If a mandatory field is missing, state which field is required.\n\n* **Mandatory Fields:** Any request to create or update a record must validate all mandatory fields.\n\n* You do not need to ask for confirmation or permission before taking action.\n\n* When identifiers such as names or IDs are missing, perform lookups, verify that you are reusing correct values from previous responses, and proceed using the retrieved data.\n\n* Never assume or fabricate IDs, responses, or outcomes \u2014 rely solely on verified API results. The same is the case of optional or default arguments.\n\n* Complete each task in a logical, and efficient execution flow.\n\n---\n\n## **2. Roles & Responsibilities and Access Scope**\n\n*(Roles renamed and permissions corrected to align with DB/Tool data: `ITIL Agent` \u2192 `Agent`, `End User` \u2192 `Reporter`. Permissions for `Agent` and `Manager` corrected.)*\n\nAccess rights are defined by roles and grant granular control across tables.\n\n| Role (DB ID) | Primary Responsibility | Core Capabilities | Critical Restrictions |\n\n| :--- | :--- | :--- | :--- |\n\n| **Administrator** (`admin`) | System Configuration & Integrity | Full CRUD (Create, Read, Update, Delete) access across all tables.\u00a0|\n\n| **Manager** (`manager`) | Supervision, Escalation, Approvals | Full CRUD on operational tables (`incident`, `problem`, `change`, `knowledge`); READ access to all the tables. Can **reassign** incidents/requests. Can **approve/reject** Change Requests. Monitors SLAs and escalations. |\n\n| **Agent** (`agent`) | Frontline Incident/Request fulfillment | **Full CRUD** on **Incidents, Service Requests, Tasks, Work Notes, CMDB, Change, Problem, and Knowledge**. READ access to all the tables. Can update assignment, state, and resolution. | Cannot bypass approvals, or change system administration settings. |\n\n| **Reporter** (`reporter`) | IT Service Consumption | Can view and update **their own submitted Incidents/Requests**. Can search **Public Knowledge** articles. | Cannot view or modify records opened by other users, CMDB, or internal work notes. |\n\n---\n\n## **3. Core Operations: Incident Management**\n\n### **3.1. Incident Registration**\n\n* **Creation:** To log any issue/interrupted service, create an **Incident** record(create_incident).\n\n* **Mandatory Inputs:** `opened_by` (user submitting), `caller_id` (user affected), `short_description`, `impact`, and `urgency`.\n\n* **Priority Calculation:** Priority (`critical`, `high`, `moderate`, `low`, `planning`) is determined automatically by the system based on a below pre-defined matrix of **Impact x Urgency**.\n\n| Impact | Urgency | Priority |\n\n| --- | --- | --- |\n\n| low | low | planning |\n\n| low | medium | low |\n\n| low | high | moderate |\n\n| medium | low | low |\n\n| medium | medium | moderate |\n\n| medium | high | high |\n\n| high | low | moderate |\n\n| high | medium | high |\n\n| high | high | critical |\n\n* **Default Status:** All new Incidents are set to `status = new`.\n\n### **3.2. Incident Assignment**\n\n* **Constraints:** `assigned_to` must be an **active** user with the `Agent` or `Manager` role and must be a member of the specified `assignment_group`.\n\n### **3.3. Incident Lifecycle and Closure**\n\n* **Valid Status Transitions:**\n\n* `new` \u2192 `in_progress` / `on_hold` / `resolved`\n\n* `in_progress` \u2192 `on_hold` / `resolved`\n\n* `on_hold` \u2192 `in_progress` (Must log `on_hold_reason` before transition)\n\n* `resolved` \u2192 `closed` / 'in_progress'\n\n* **Resolution Requirement:** An Incident cannot transition to `resolved` without mandatory fields: `resolution_code`, and `resolution_notes` (free-form text, max 2000 chars).\n\n* **Closure Policy:** The incidents that are in `resolved` status will transition to `closed` after 72 hours.\n\n---\n\n## **4. Core Operations: Change and Problem Management**\n\n### **4.1. Change Management**\n\n* **Creation:** All changes must originate from a **Change Request** record.\n\n* **Default Status:** All new Changes are set to `status = new`.\n\n* **Change Types (Enumeration):** `standard` (pre-approved, low risk), `normal` (requires planning/approval), `emergency` (requires immediate CAB approval override).\n\n### **4.2. Problem Management**\n\n* **Trigger:** A Problem must be created (`create_problem`) when a recurring incident pattern or a major incident is identified.\n\n* **Linking:** The Problem record **must** link all affected Incidents via the `incident_to_problem` related list.\n\n* **Default Status:** All new Problems are set to `status = new`.\n\n* **Workaround:** If workaround/temporary solution found, update workaround field and set status=`fix_in_progress`. The `workaround_notes` **must** be published to the linked Incidents and relevant Knowledge Articles.\n\n* **Final Status:** A Problem transitions to `closed` only after the permanent fix has been successfully implemented via a linked `normal` or `emergency` Change Request.\n\n* **Priority Calculation:** Priority (`critical`, `high`, `moderate`, `low`, `planning`) is determined automatically by the system based on a below pre-defined matrix of **Impact x Urgency**.\n\n| Impact | Urgency | Priority |\n\n| --- | --- | --- |\n\n| low | low | planning |\n\n| low | medium | low |\n\n| low | high | moderate |\n\n| medium | low | low |\n\n| medium | medium | moderate |\n\n| medium | high | high |\n\n| high | low | moderate |\n\n| high | medium | high |\n\n| high | high | critical |\n\n---\n\n## **5. Configuration and Service Management (CMDB)**\n\n### **5.1. Configuration Item (CI) Integrity**\n\n* **Table:** All IT assets must be recorded in the `configuration_item` table.\n\n* **CI Status:** Only CIs with `status = in_use` or `status = maintenance` can be linked to active Incidents. Do not link CIs in `status = retired` or `status = disposed`.\n\n* **CI Owner:** All CIs must have a recorded `owner_id`.\n\n---\n\n## **6. Service Level Management (SLA)**\n\n* **SLA Application:** SLAs are automatically aligned based on `priority` linked to the incident.\n\n* **Metric:** Metrics tracked are limited to `target_mins`.\n\n* **SLA Pause:** The SLA timer **must** be paused (`stage = paused`) when the Incident is in `stage = on_hold` and the `on_hold_reason` is one of the following enumerations: `Awaiting Change`, `Awaiting Caller`, or `Awaiting Problem`.\n\n* **Breach:** If the SLA exceeds its duration (`stage = breached`), the `escalation` flag on the Incident **must** be set to true, and an automatic notification sent to the `Manager`.\n\n---\n\n## **7. Knowledge Management**\n\n* **Article Status:** Only articles in `knowledge.state = published` are searchable by the `Reporter` role.\n\n* **Search Policy:** When an Incident is created, a search for relevant knowledge must be performed, and matching articles linked as `used_as = suggested`.\n\n* **Use Tracking:** All knowledge links must track `used_as` type: `suggested`, `applied`, or `resolution`.\n\n---\n\n## **8. Validation, Error Handling, and Logging**\n\n### **8.1. Data Integrity Checks**\n\n* **User Status:** Ensure any user being assigned to (`assigned_to`) or updated is `users.active = true`.\n\n* **Referential Integrity:** Before closing any record, verify that all mandatory dependencies are satisfied.\n\n* **Time Tracking:** All work logs must include the timestamp (`created_on`) and the `user_id` performing the action.\n\n### **8.2. Error Handling**\n\n* **403 Forbidden:** Permission denied (user role lacks authority for the operation).\n\n* **409 Conflict:** Record locking or state conflict.\n\n* **Rate Limiting:** If exceeded, pause and retry using **Exponential Backoff**.\n\n---\n\n## **9. Predefined Lists (Enumerations)**\n\n| Table.Field | Allowed Values |\n\n| :--- | :--- |\n\n| **users.role** | `admin`, `manager`, `agent`, `reporter` |\n\n| **incident.priority** | `critical`, `high`, `moderate`, `low`, `planning` |\n\n| **incident.impact** | `high`, `medium`, `low` |\n\n| **incident.urgency** | `high`, `medium`, `low` |\n\n| **incident.status** | `new`, `in_progress`, `on_hold`, `resolved`, `closed` |\n\n| **incident.on_hold_reason** | `Awaiting Change`, `Awaiting Caller`, `Awaiting Problem` |\n\n| **incident.resolution_code** | `fixed`, `workaround`, `not_reproducible`, `closed_by_caller` |\n\n| **change_request.type** | `standard`, `normal`, `emergency` |\n\n| **change_request.status** | `new`, `assess`, `authorize`, `scheduled`, `implement`, `review`, `closed`, `canceled` |\n\n| **configuration_item.status** | `in_use`, `in_stock`, `maintenance`, `retired`, `disposed` |\n\n| **kb_knowledge.state** | `draft`, `review`, `published`, `retired` |\n\n| **incident_sla.stage** | `in_progress`, `paused`, `completed`, `cancelled`, `breached` |"}, {"role": "user", "content": "An update came in from the caller regarding the printer connectivity issue for incident INC0000003. The user stated that several urgent client documents are still pending, and the inability to print is causing significant delays. Although the submission deadline has been extended by one business day, the service impact remains significant. Therefore increase the impact of the incident to high and update the necessary details."}], "tools": [{"type": "function", "name": "get_user", "description": "Retrieve a user by their user ID.\n \n Use this tool to find a specific user using their unique user_id identifier.\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Parameters:\n - user_id (required): User's unique identifier (format: USER_001, USER_002, etc.)\n \n Returns a single user object if found, or an error if the user doesn't exist.", "parameters": {"type": "object", "properties": {"user_id": {"type": "string", "description": "User's unique identifier (String, max 32 characters)"}}, "required": ["user_id"]}, "strict": false}, {"type": "function", "name": "find_incident_by_number", "description": "Retrieve an incident by its incident number.\n \n Use this tool to find a specific incident using its unique incident number.\n \n Parameters:\n - number (required): Incident number (e.g., INC-000001)\n \n Returns a single incident object if found, or an error if the incident doesn't exist.", "parameters": {"type": "object", "properties": {"number": {"type": "string", "description": "Incident number (e.g., INC-000001)"}}, "required": ["number"]}, "strict": false}, {"type": "function", "name": "update_incident", "description": "Update an existing incident in the system.\n \n Use this tool to update an existing incident with the specified details.\n \n Required Parameters:\n - incident_id: ID of the incident to update\n \n Optional Parameters:\n - number: Incident number\n - service: Service ID related to the incident\n - service_offering: Service offering ID related to the incident\n - configuration_item: Configuration item ID related to the incident\n - caller_id: ID of the user who reported the incident\n - channel: How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)\n - status: Current status of the incident (new, in_progress, on_hold, resolved, closed, canceled)\n - category: Category of the incident (inquiry-help, software, hardware, database, password-reset, network)\n - short_description: Brief description of the incident\n - description: Detailed description of the incident\n - impact: Impact level (high, medium, low)\n - urgency: Urgency level (high, medium, low)\n - priority: Priority level (critical, high, moderate, low, planning)\n - assigned_to: User ID to assign the incident to\n - assignment_group: Group ID to assign the incident to\n - worknotes: Work notes for the incident\n - resolution_notes: Resolution notes for the incident\n - close_notes: Close notes for the incident\n - resolution_code: Resolution code for the incident\n - parent_incident: Parent incident ID if this is a child incident\n - problem: Problem ID related to the incident\n - change_request: Change request ID related to the incident\n - caused_by_change: Change ID that caused this incident\n - resolved_by: User ID who resolved the incident\n - on_hold_reason: Reason why the incident is on hold\n - incident_template: Incident template ID to use\n - resolved: Timestamp when the incident was resolved\n \n Returns the updated incident object with all fields.", "parameters": {"type": "object", "properties": {"incident_id": {"type": "string", "description": "ID of the incident to update"}, "number": {"type": "string", "description": "Incident number"}, "service": {"type": "string", "description": "Service ID related to the incident"}, "service_offering": {"type": "string", "description": "Service offering ID related to the incident"}, "configuration_item": {"type": "string", "description": "Configuration item ID related to the incident"}, "caller_id": {"type": "string", "description": "ID of the user who reported the incident"}, "channel": {"type": "string", "description": "How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)", "enum": ["self-service", "phone", "email", "chat", "walk-in", "virtual-agent"]}, "status": {"type": "string", "description": "Current status of the incident", "enum": ["new", "in_progress", "on_hold", "resolved", "closed", "canceled"]}, "category": {"type": "string", "description": "Category of the incident", "enum": ["inquiry-help", "software", "hardware", "database", "password-reset", "network"]}, "short_description": {"type": "string", "description": "Brief description of the incident"}, "description": {"type": "string", "description": "Detailed description of the incident"}, "impact": {"type": "string", "description": "Impact level", "enum": ["high", "medium", "low"]}, "urgency": {"type": "string", "description": "Urgency level", "enum": ["high", "medium", "low"]}, "priority": {"type": "string", "description": "Priority level", "enum": ["critical", "high", "moderate", "low", "planning"]}, "assigned_to": {"type": "string", "description": "User ID to assign the incident to"}, "assignment_group": {"type": "string", "description": "Group ID to assign the incident to"}, "worknotes": {"type": "string", "description": "Work notes for the incident"}, "resolution_notes": {"type": "string", "description": "Resolution notes for the incident"}, "close_notes": {"type": "string", "description": "Close notes for the incident"}, "resolution_code": {"type": "string", "description": "Resolution code for the incident", "enum": ["Duplicate", "Known Error", "No resolution provided", "Resolved By Caller", "Resolved By Problem", "Resolved By Change", "Solution Provided", "Workaround Provided", "User error"]}, "parent_incident": {"type": "string", "description": "Parent incident ID if this is a child incident"}, "problem": {"type": "string", "description": "Problem ID related to the incident"}, "change_request": {"type": "string", "description": "Change request ID related to the incident"}, "caused_by_change": {"type": "string", "description": "Change ID that caused this incident"}, "resolved_by": {"type": "string", "description": "User ID who resolved the incident"}, "on_hold_reason": {"type": "string", "description": "Reason why the incident is on hold", "enum": ["Awaiting Change", "Awaiting Caller", "Awaiting Problem"]}, "incident_template": {"type": "string", "description": "Incident template ID to use"}, "resolved": {"type": "string", "description": "Timestamp when the incident was resolved (ISO 8601 format)"}}, "required": ["incident_id"]}, "strict": false}, {"type": "function", "name": "find_sla_definitions", "description": "List SLA definitions applying optional filters. Returns all SLA definitions if no filters provided.\n\nSupported filters (all optional):\n- sla_def_id, name\n- metric (RESPONSE, RESOLUTION)\n- target_mins, pause_on_pending, active\n- applies_to_priority (CRITICAL, HIGH, MODERATE, LOW)\n- created_after, created_before (ISO timestamp strings)\n\nNote:\n- Empty strings (\"\") or null values for parameters will return all results without filtering\n- For boolean fields (pause_on_pending, active), only use true/false to filter - null will return all results\n\nExample:\n{\n \"metric\": \"RESPONSE\",\n \"active\": true,\n \"applies_to_priority\": \"CRITICAL\"\n}", "parameters": {"type": "object", "properties": {"sla_def_id": {"type": "string", "description": "Filter by sla_def_id"}, "name": {"type": "string", "description": "Filter by name"}, "metric": {"type": "string", "enum": ["response", "resolution"], "description": "Filter by metric (response or resolution). Null returns all."}, "target_mins": {"type": "integer", "description": "Filter by target_mins"}, "pause_on_pending": {"type": "boolean", "description": "Filter by pause_on_pending. Null returns all."}, "applies_to_priority": {"type": "string", "enum": ["critical", "high", "moderate", "low"], "description": "Filter by applies_to_priority. Null returns all."}, "active": {"type": "boolean", "description": "Filter by active status. Null returns all."}, "created_after": {"type": "string", "description": "ISO timestamp: return SLA definitions created after this value"}, "created_before": {"type": "string", "description": "ISO timestamp: return SLA definitions created before this value"}}, "required": []}, "strict": false}, {"type": "function", "name": "find_incident_slas", "description": "List Incident SLA records with optional filters.\nAll parameters are optional; omitting them returns every incident SLA for the caller's organization.", "parameters": {"type": "object", "properties": {"incident_sla_id": {"type": "string", "description": "Filter by SLA record ID"}, "incident_id": {"type": "string", "description": "Filter by incident ID"}, "sla_def_id": {"type": "string", "description": "Filter by SLA definition ID"}, "stage": {"type": "string", "description": "Filter by stage (in_progress, paused, completed, cancelled, breached)"}, "has_breached": {"type": "boolean", "description": "Filter by breach flag"}, "created_before": {"type": "string", "description": "ISO timestamp (<=) filter on created_on"}, "created_after": {"type": "string", "description": "ISO timestamp (>=) filter on created_on"}}}, "strict": false}, {"type": "function", "name": "link_new_incident_sla", "description": "Create a new Incident SLA record (incident_sla).\nRequires incident_id, sla_def_id, and start_time. Stage defaults to IN_PROGRESS.", "parameters": {"type": "object", "properties": {"incident_id": {"type": "string", "description": "Incident identifier"}, "sla_def_id": {"type": "string", "description": "SLA definition identifier"}, "stage": {"type": "string", "description": "Stage (in_progress, paused, completed, cancelled, breached)"}, "has_breached": {"type": "boolean", "description": "Whether SLA has breached"}, "start_time": {"type": "string", "description": "Start time (ISO timestamp)"}, "breach_time": {"type": "string", "description": "Breach time (ISO timestamp)"}, "completed_time": {"type": "string", "description": "Completion time (ISO timestamp)"}}, "required": ["incident_id", "sla_def_id", "start_time"]}, "strict": false}]}, "verifier_metadata": {"task_id": "task_20251212_172511_458_e6427839_47076c15", "domain": "itsm", "mode": "oracle", "gym_servers_config": [{"mcp_server_name": "gym-itsm-mcp", "mcp_server_url": "http://localhost:8006", "seed_database_file": "Domain Wise DBs and Task-DB Mappings/itsm/dbs/db_1765301900121_3mwjj54xy.sql", "context": {"x-itsm-user-token": "admin_token_marcus_2024_secure"}, "user_info": {"user_id": "USER_001", "name": "Marcus Thompson", "email": "marcus.thompson@techcorp.com"}}], "verifiers": [{"verifier_type": "database_state", "name": "Verify if the priority of the incident is set correctly.", "description": "Verify if the priority of the incident is set correctly.", "gym_name": "gym-itsm-mcp", "validation_config": {"query": "SELECT COUNT(*) FROM incident WHERE incident_id = 'INC_003' AND impact = 'high' AND priority = 'high';\n", "expected_value": 1, "comparison_type": "equals"}}, {"verifier_type": "database_state", "name": "Verify if the correct high-priority SLA is linked to the incident.", "description": "Verify if the correct high-priority SLA is linked to the incident.", "gym_name": "gym-itsm-mcp", "validation_config": {"query": "SELECT COUNT(*) FROM incident_sla WHERE incident_id = 'INC_003' AND sla_def_id = 'SLA_002';\n", "expected_value": 1, "comparison_type": "equals"}}], "selected_tools": ["find_sla_definitions", "find_incident_slas", "find_incident_by_number", "get_user", "update_incident", "link_new_incident_sla"], "restricted_tools": [], "tool_to_gym": {"get_user": "gym-itsm-mcp", "find_incident_by_number": "gym-itsm-mcp", "update_incident": "gym-itsm-mcp", "find_sla_definitions": "gym-itsm-mcp", "find_incident_slas": "gym-itsm-mcp", "link_new_incident_sla": "gym-itsm-mcp"}}}
diff --git a/resources_servers/enterpriseops_gym/data/tools/calendar.json b/resources_servers/enterpriseops_gym/data/tools/calendar.json
new file mode 100644
index 0000000000..d745b86b31
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/calendar.json
@@ -0,0 +1,3436 @@
+{
+ "gym_name": "gym-calendar",
+ "gym_url": "http://localhost:8003",
+ "snapshot_at": "2026-07-07T18:18:25.375390+00:00",
+ "tools": [
+ {
+ "name": "create_calendar",
+ "description": "Create a new secondary calendar.\n\n Creates a new calendar following Google Calendar API v3 structure. This endpoint\n strictly creates a secondary calendar. It does not create or promote a primary calendar.\n The user must already exist; otherwise a 404 is returned.\n\n Request Body Requirements:\n - summary: Required. Calendar title (1-255 characters)\n - description: Optional. Calendar description (max 1000 characters)\n - location: Optional. Geographic location (max 500 characters)\n - timeZone: Optional. Calendar timezone in IANA format (default: UTC)\n - conferenceProperties: Optional. Conference solution settings\n\n Notes:\n - This operation cannot create a primary calendar. Use account provisioning or separate tooling to ensure a primary exists.\n\n Response Structure:\n - Returns the created calendar with Google Calendar API v3 format:\n * kind: \"calendar#calendar\"\n * etag: ETag of the resource\n * id: Unique calendar identifier (UUID)\n * summary: Calendar title\n * description: Calendar description (if provided)\n * location: Calendar location (if provided)\n * timeZone: Calendar timezone\n * conferenceProperties: Conference settings (if provided)\n\n Status Codes:\n - 201: Created - Calendar created successfully\n - 400: Bad Request - Invalid calendar data\n - 404: Not Found - User not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "summary": {
+ "type": "string",
+ "description": "Calendar title (1-255 characters)",
+ "minLength": 1,
+ "maxLength": 255
+ },
+ "description": {
+ "type": "string",
+ "description": "Calendar description (max 1000 characters)",
+ "maxLength": 1000
+ },
+ "location": {
+ "type": "string",
+ "description": "Geographic location (max 500 characters)",
+ "maxLength": 500
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Calendar timezone in IANA format (default: UTC)",
+ "default": "UTC"
+ },
+ "conferenceProperties": {
+ "type": "object",
+ "description": "Conference solution settings",
+ "properties": {
+ "allowedConferenceSolutionTypes": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "eventHangout",
+ "eventNamedHangout",
+ "hangoutsMeet"
+ ]
+ },
+ "description": "Allowed conference solution types"
+ }
+ }
+ }
+ },
+ "required": [
+ "summary"
+ ]
+ }
+ },
+ {
+ "name": "get_calendar",
+ "description": "Retrieve a specific calendar by its ID (supports 'primary').\n\n Returns calendar metadata following Google Calendar API v3 structure.\n Supports using the special keyword 'primary' as the calendar identifier to\n target the user's primary calendar.\n\n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or the keyword 'primary'\n\n Response Structure:\n - Returns calendar with Google Calendar API v3 format:\n * kind: \"calendar#calendar\"\n * etag: ETag of the resource\n * id: Unique calendar identifier\n * summary: Calendar title\n * description: Calendar description (if present)\n * location: Calendar location (if present)\n * timeZone: Calendar timezone\n * conferenceProperties: Conference settings (if present)\n\n Status Codes:\n - 200: Success - Calendar retrieved successfully\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID) or the keyword 'primary'",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "patch_calendar",
+ "description": "Partially update calendar metadata (cannot change which calendar is primary).\n\n Partially updates calendar metadata following Google Calendar API v3 structure.\n Only provided fields will be updated, others remain unchanged.\n You can update both primary and secondary calendars.\n Supports using the special keyword 'primary' as the calendar identifier.\n\n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or the keyword 'primary'\n\n Request Body (all optional):\n - summary: Calendar title (1-255 characters)\n - description: Calendar description (max 1000 characters)\n - location: Geographic location (max 500 characters)\n - timeZone: Calendar timezone in IANA format\n - conferenceProperties: Conference solution settings\n\n Restrictions:\n - Cannot modify which calendar is primary (the is_primary flag is immutable via PATCH)\n - At least one field must be provided for update\n - Primary status is automatically assigned and protected\n\n Response Structure:\n - Returns updated calendar with Google Calendar API v3 format\n\n Status Codes:\n - 200: Success - Calendar updated successfully\n - 400: Bad Request - No fields provided or attempt to modify primary status\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID) or the keyword 'primary'",
+ "minLength": 1
+ },
+ "summary": {
+ "type": "string",
+ "description": "Calendar title (1-255 characters)",
+ "minLength": 1,
+ "maxLength": 255
+ },
+ "description": {
+ "type": "string",
+ "description": "Calendar description (max 1000 characters)",
+ "maxLength": 1000
+ },
+ "location": {
+ "type": "string",
+ "description": "Geographic location (max 500 characters)",
+ "maxLength": 500
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Calendar timezone in IANA format"
+ },
+ "conferenceProperties": {
+ "type": "object",
+ "description": "Conference solution settings",
+ "properties": {
+ "allowedConferenceSolutionTypes": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "eventHangout",
+ "eventNamedHangout",
+ "hangoutsMeet"
+ ]
+ },
+ "description": "Allowed conference solution types"
+ }
+ }
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "update_calendar",
+ "description": "Fully update calendar metadata (cannot change which calendar is primary).\n\n Completely updates calendar metadata following Google Calendar API v3 structure.\n All provided fields replace existing values. Optional fields omitted will remain unchanged\n in the current implementation. You can update both primary and secondary calendars.\n Primary calendar status (which calendar is primary) cannot be modified via this endpoint.\n Supports using the special keyword 'primary' as the calendar identifier.\n\n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or the keyword 'primary'\n\n Request Body (all optional; null clears for description/location/conferenceProperties):\n - summary: Calendar title (1-255 characters)\n - description: Calendar description (max 1000 characters) - null to clear\n - location: Geographic location (max 500 characters) - null to clear\n - timeZone: Calendar timezone in IANA format\n - conferenceProperties: Conference solution settings - null to clear\n\n Restrictions:\n - Cannot modify which calendar is primary (the is_primary flag is immutable via PUT)\n\n Response Structure:\n - Returns updated calendar with Google Calendar API v3 format\n\n Status Codes:\n - 200: Success - Calendar updated successfully\n - 400: Bad Request - Invalid update data or attempt to modify primary status\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID) or the keyword 'primary'",
+ "minLength": 1
+ },
+ "summary": {
+ "type": "string",
+ "description": "Calendar title (1-255 characters)",
+ "minLength": 1,
+ "maxLength": 255
+ },
+ "description": {
+ "type": "string",
+ "description": "Calendar description (max 1000 characters)",
+ "maxLength": 1000
+ },
+ "location": {
+ "type": "string",
+ "description": "Geographic location (max 500 characters)",
+ "maxLength": 500
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Calendar timezone in IANA format"
+ },
+ "conferenceProperties": {
+ "type": "object",
+ "description": "Conference solution settings",
+ "properties": {
+ "allowedConferenceSolutionTypes": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "eventHangout",
+ "eventNamedHangout",
+ "hangoutsMeet"
+ ]
+ },
+ "description": "Allowed conference solution types"
+ }
+ }
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "delete_calendar",
+ "description": "Delete a secondary calendar (cannot delete primary calendar).\n\n Deletes a calendar following Google Calendar API v3 behavior.\n Primary calendars cannot be deleted - use clear operation instead.\n\n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID)\n\n Primary Calendar Protection:\n - Primary calendars cannot be deleted\n - Attempting to delete primary calendar returns 400 Bad Request\n - Use clear_calendar tool to remove events from primary calendar\n\n Cascade Behavior:\n - Deleting a calendar also deletes all associated events\n - This operation is irreversible\n\n Response Structure:\n - Returns 204 No Content on successful deletion\n - No response body as per Google Calendar API v3\n\n Status Codes:\n - 204: No Content - Calendar deleted successfully\n - 400: Bad Request - Attempted to delete primary calendar\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "clear_calendar",
+ "description": "Clear all events from a calendar (useful for primary calendars).\n\n Clears all events from a calendar following Google Calendar API v3 behavior.\n This is the recommended way to \"reset\" a primary calendar since primary calendars cannot be deleted.\n\n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID)\n\n Operation Details:\n - Removes all events from the specified calendar\n - Calendar metadata remains unchanged\n - Useful for primary calendars that cannot be deleted\n - Can be used on any calendar (primary or secondary)\n\n Response:\n - Returns 204 No Content on successful clear (no response body)\n\n Status Codes:\n - 204: No Content - Calendar cleared successfully\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "get_calendar_list",
+ "description": "Returns the calendars on the user's calendar list.\n \n Lists all calendars in the user's calendar list with their display settings and access permissions.\n Returns calendars with user-specific customizations like colors, visibility, and notification settings.\n Supports pagination through pageToken and incremental synchronization through syncToken.\n \n Request Body Requirements:\n - maxResults: Optional. Maximum number of entries returned (pagination). If 0, returns no items.\n - minAccessRole: Optional. Minimum access role filter (freeBusyReader, reader, writer, owner)\n - pageToken: Optional. Token specifying which result page to return (for pagination)\n - showDeleted: Optional. Include deleted calendars in results (default: false)\n - showHidden: Optional. Include hidden calendars in results (default: false)\n - syncToken: Optional. Token for incremental synchronization (returns only changed entries)\n \n Pagination Support:\n - Use maxResults to limit the number of calendars returned per page\n - Use pageToken to retrieve subsequent pages of results\n - Check nextPageToken in response to determine if more results are available\n - Pass nextPageToken as pageToken in the next request to get the next page\n \n Incremental Synchronization:\n - Use syncToken to get only entries that have changed since the last request\n - syncToken cannot be used together with minAccessRole parameter\n - When using syncToken, deleted and hidden entries are automatically included\n - If syncToken expires, server returns 410 GONE and client should perform full sync\n - Use nextSyncToken from response for subsequent incremental sync requests\n \n Response Structure:\n - Returns calendar list collection with Google Calendar API v3 format:\n * kind: \"calendar#calendarList\"\n * etag: ETag of the collection\n * items: Array of CalendarListEntry objects\n * nextPageToken: Token for next page (if more results available)\n * nextSyncToken: Token for incremental sync (always provided when items are returned)\n \n CalendarListEntry Structure:\n - Each item contains calendar metadata plus user-specific settings:\n * id: Calendar identifier\n * summary: Display title (with summaryOverride if set)\n * accessRole: User's permission level\n * primary: Whether it's the user's primary calendar\n * backgroundColor/foregroundColor: Display colors\n * hidden: Whether hidden from calendar list\n * selected: Whether selected in UI\n * defaultReminders: User-specific default reminders\n * notificationSettings: Notification preferences\n \n Status Codes:\n - 200: Success - Calendar list retrieved successfully\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of entries returned. If 0, returns no items.",
+ "minimum": 0,
+ "maximum": 250,
+ "default": 100
+ },
+ "minAccessRole": {
+ "type": "string",
+ "description": "Minimum access role filter",
+ "enum": [
+ "freeBusyReader",
+ "reader",
+ "writer",
+ "owner"
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Token specifying which result page to return (for pagination)"
+ },
+ "showDeleted": {
+ "type": "boolean",
+ "description": "Include deleted calendars in results",
+ "default": false
+ },
+ "showHidden": {
+ "type": "boolean",
+ "description": "Include hidden calendars in results",
+ "default": false
+ },
+ "syncToken": {
+ "type": "string",
+ "description": "Token for incremental synchronization (returns only changed entries since last sync)"
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "get_calendar_from_list",
+ "description": "Returns a calendar from the user's calendar list.\n \n Retrieves a specific calendar entry from the user's calendar list with all user-specific settings.\n Shows how the calendar appears in the user's list with customizations and access permissions.\n \n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or the keyword 'primary' to refer to the user's primary calendar\n \n Response Structure:\n - Returns CalendarListEntry with Google Calendar API v3 format:\n * kind: \"calendar#calendarListEntry\"\n * etag: ETag of the resource\n * id: Calendar identifier\n * summary: Display title (with summaryOverride if set)\n * description: Calendar description\n * location: Calendar location\n * timeZone: Calendar timezone\n * summaryOverride: Custom title override for this user\n * colorId: Calendar color ID\n * backgroundColor: Background color (hex)\n * foregroundColor: Foreground color (hex)\n * hidden: Whether hidden from calendar list\n * selected: Whether selected in UI\n * accessRole: User's permission level (freeBusyReader, reader, writer, owner)\n * defaultReminders: User-specific default reminders\n * notificationSettings: Notification preferences\n * primary: Whether it's the user's primary calendar\n * deleted: Whether the calendar is deleted\n \n Status Codes:\n - 200: Success - Calendar entry retrieved successfully\n - 404: Not Found - Calendar not found in user's list\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "add_calendar_to_list",
+ "description": "Inserts an existing calendar into the user's calendar list.\n \n Adds an existing calendar to the user's calendar list with custom display settings.\n The calendar must already exist - this endpoint only adds it to the user's list with personalization.\n \n Request Body Requirements:\n - id: Required. Calendar ID to add to user's list\n - summaryOverride: Optional. Custom calendar title override\n - colorId: Optional. Calendar color ID\n - backgroundColor: Optional. Background color (hex format like #FF5733)\n - foregroundColor: Optional. Foreground color (hex format like #FFFFFF)\n - hidden: Optional. Whether calendar is hidden from list (default: false)\n - selected: Optional. Whether calendar is selected in UI (default: true)\n - defaultReminders: Optional. Array of default reminder settings\n - notificationSettings: Optional. Notification preferences\n \n Calendar Must Exist:\n - The calendar with the specified ID must already exist in the database\n - This endpoint does not create new calendars, only adds them to user's list\n - Use create_calendar tool first if the calendar doesn't exist\n \n Response Structure:\n - Returns the created CalendarListEntry with Google Calendar API v3 format\n - Includes all user-specific customizations applied\n \n Colors:\n - To set backgroundColor/foregroundColor you must pass query param colorRgbFormat=true\n - When RGB fields are provided, colorId (if present) is ignored\n \n Status Codes:\n - 201: Created - Calendar added to list successfully\n - 404: Not Found - Calendar with specified ID not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Calendar ID to add to user's list (UUID)",
+ "minLength": 1
+ },
+ "colorRgbFormat": {
+ "type": "boolean",
+ "description": "Query param: if true, allows writing backgroundColor/foregroundColor",
+ "default": false
+ },
+ "summaryOverride": {
+ "type": "string",
+ "description": "Custom calendar title override",
+ "maxLength": 255
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Calendar color ID",
+ "maxLength": 50
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "Background color (hex format like #FF5733)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "foregroundColor": {
+ "type": "string",
+ "description": "Foreground color (hex format like #FFFFFF)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether calendar is hidden from list",
+ "default": false
+ },
+ "selected": {
+ "type": "boolean",
+ "description": "Whether calendar is selected in UI",
+ "default": true
+ },
+ "defaultReminders": {
+ "type": "array",
+ "description": "Default reminder settings",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ],
+ "description": "Reminder delivery method"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event to trigger reminder",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "method",
+ "minutes"
+ ]
+ }
+ },
+ "notificationSettings": {
+ "type": "object",
+ "description": "Notification preferences",
+ "properties": {
+ "notifications": {
+ "type": "array",
+ "description": "List of notification settings",
+ "items": {
+ "type": "object",
+ "description": "Individual notification setting",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email"
+ ],
+ "description": "Notification delivery method (only 'email' supported)"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "eventCreation",
+ "eventChange",
+ "eventCancellation",
+ "eventResponse",
+ "agenda"
+ ],
+ "description": "Notification type"
+ }
+ },
+ "required": [
+ "method",
+ "type"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "update_calendar_in_list",
+ "description": "Updates an entry on the user's calendar list (partial update).\n \n Partially updates calendar list entry settings. Only provided fields will be updated,\n others remain unchanged. This allows fine-grained control over calendar display settings.\n \n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or 'primary'\n \n Request Body (all optional):\n - summaryOverride: Custom calendar title override\n - colorId: Calendar color ID\n - backgroundColor: Background color (hex format like #FF5733)\n - foregroundColor: Foreground color (hex format like #FFFFFF)\n - hidden: Whether calendar is hidden from list\n - selected: Whether calendar is selected in UI\n - defaultReminders: Array of default reminder settings\n - notificationSettings: Notification preferences\n \n Partial Update Behavior:\n - Only fields provided in request body are updated\n - Null values will clear the field (set to null) for string/complex fields\n - 'hidden' and 'selected' cannot be null (booleans are NOT NULL in our DB)\n - Missing fields are left unchanged\n - At least one field must be provided for update\n\n Response Structure:\n - Returns updated CalendarListEntry with Google Calendar API v3 format\n - Shows all current settings including unchanged fields\n\n Colors:\n - To set backgroundColor/foregroundColor you must pass query param colorRgbFormat=true\n - When RGB fields are provided, colorId (if present) is ignored\n\n Behavioral coupling:\n - If hidden=true, the server will force selected=false\n - If hidden=false, the server will force selected=true (matches observed UI behavior)\n \n Status Codes:\n - 200: Success - Calendar list entry updated successfully\n - 400: Bad Request - No fields provided for update\n - 404: Not Found - Calendar not found in user's list\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ },
+ "colorRgbFormat": {
+ "type": "boolean",
+ "description": "Query param: if true, allows writing backgroundColor/foregroundColor",
+ "default": false
+ },
+ "summaryOverride": {
+ "type": "string",
+ "description": "Custom calendar title override",
+ "maxLength": 255
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Calendar color ID",
+ "maxLength": 50
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "Background color (hex format like #FF5733)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "foregroundColor": {
+ "type": "string",
+ "description": "Foreground color (hex format like #FFFFFF)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether calendar is hidden from list",
+ "default": false
+ },
+ "selected": {
+ "type": "boolean",
+ "description": "Whether calendar is selected in UI",
+ "default": true
+ },
+ "defaultReminders": {
+ "type": "array",
+ "description": "Default reminder settings",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ],
+ "description": "Reminder delivery method"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event to trigger reminder",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "method",
+ "minutes"
+ ]
+ }
+ },
+ "notificationSettings": {
+ "type": "object",
+ "description": "Notification preferences",
+ "properties": {
+ "notifications": {
+ "type": "array",
+ "description": "List of notification settings",
+ "items": {
+ "type": "object",
+ "description": "Individual notification setting",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email"
+ ],
+ "description": "Notification delivery method (only 'email' supported)"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "eventCreation",
+ "eventChange",
+ "eventCancellation",
+ "eventResponse",
+ "agenda"
+ ],
+ "description": "Notification type"
+ }
+ },
+ "required": [
+ "method",
+ "type"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "replace_calendar_in_list",
+ "description": "Updates an entry on the user's calendar list (full update).\n \n Fully updates calendar list entry settings. All fields are replaced with provided values.\n Fields not provided will be set to their default values (full replacement).\n \n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID) or 'primary'\n \n Request Body (all optional, but null/missing values will be set to defaults):\n - summaryOverride: Custom calendar title override (null to clear)\n - colorId: Calendar color ID (null to clear)\n - backgroundColor: Background color (hex format like #FF5733, null to clear)\n - foregroundColor: Foreground color (hex format like #FFFFFF, null to clear)\n - hidden: Whether calendar is hidden from list (default: false)\n - selected: Whether calendar is selected in UI (default: true)\n - defaultReminders: Array of default reminder settings (null to clear)\n - notificationSettings: Notification preferences (null to clear)\n - conferenceProperties: Conference properties for this calendar (null to clear)\n \n Full Update Behavior:\n - All fields are replaced (full replacement operation)\n - Missing optional fields are set to null/defaults\n - Required fields (hidden, selected) get default values if not provided\n - This is different from PATCH which only updates provided fields\n\n Response Structure:\n - Returns updated CalendarListEntry with Google Calendar API v3 format\n - Shows all current settings after full update\n\n Colors:\n - To set backgroundColor/foregroundColor you must pass query param colorRgbFormat=true\n - When RGB fields are provided, colorId (if present) is ignored\n\n Behavioral coupling:\n - If hidden=true, the server will force selected=false\n - If hidden=false, the server will force selected=true (matches observed UI behavior)\n \n Status Codes:\n - 200: Success - Calendar list entry updated successfully\n - 404: Not Found - Calendar not found in user's list\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ },
+ "colorRgbFormat": {
+ "type": "boolean",
+ "description": "Query param: if true, allows writing backgroundColor/foregroundColor",
+ "default": false
+ },
+ "summaryOverride": {
+ "type": "string",
+ "description": "Custom calendar title override",
+ "maxLength": 255
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Calendar color ID",
+ "maxLength": 50
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "Background color (hex format like #FF5733)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "foregroundColor": {
+ "type": "string",
+ "description": "Foreground color (hex format like #FFFFFF)",
+ "pattern": "^#[0-9A-Fa-f]{6}$"
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether calendar is hidden from list",
+ "default": false
+ },
+ "selected": {
+ "type": "boolean",
+ "description": "Whether calendar is selected in UI",
+ "default": true
+ },
+ "defaultReminders": {
+ "type": "array",
+ "description": "Default reminder settings",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "description": "Reminder delivery method (email, popup). Empty string allowed to clear"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event to trigger reminder",
+ "minimum": 0
+ }
+ }
+ }
+ },
+ "notificationSettings": {
+ "type": "object",
+ "description": "Notification preferences",
+ "properties": {
+ "notifications": {
+ "type": "array",
+ "description": "List of notification settings",
+ "items": {
+ "type": "object",
+ "description": "Individual notification setting",
+ "properties": {
+ "method": {
+ "type": "string",
+ "description": "Notification delivery method. Empty string allowed to clear"
+ },
+ "type": {
+ "type": "string",
+ "description": "Notification type. Empty string allowed to clear"
+ }
+ }
+ }
+ }
+ }
+ },
+ "conferenceProperties": {
+ "type": "object",
+ "description": "Conference properties for this calendar",
+ "properties": {
+ "allowedConferenceSolutionTypes": {
+ "type": "array",
+ "description": "The types of conference solutions that are supported for this calendar",
+ "items": {
+ "type": "string",
+ "enum": [
+ "eventHangout",
+ "eventNamedHangout",
+ "hangoutsMeet"
+ ],
+ "description": "Conference solution type"
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "remove_calendar_from_list",
+ "description": "Removes a calendar from the user's calendar list.\n \n Removes a calendar from the user's calendar list (soft delete).\n The calendar itself remains in the database but is no longer visible in the user's list.\n Primary calendars cannot be removed from the calendar list.\n \n Request Body Requirements:\n - calendarId: Required. Unique calendar identifier (UUID)\n \n Primary Calendar Protection:\n - Primary calendars cannot be removed from the calendar list\n - Attempting to remove primary calendar returns 400 Bad Request\n - Primary calendars are always part of the user's list\n \n Operation Details:\n - Calendar is soft-deleted (marked as deleted, not physically removed)\n - Calendar data remains in database but is hidden from list\n - Calendar can potentially be re-added to list later\n - Does not affect the underlying calendar data or events\n \n Response Structure:\n - Returns 204 No Content on successful removal\n - No response body as per Google Calendar API v3\n \n Status Codes:\n - 204: No Content - Calendar removed from list successfully\n - 400: Bad Request - Attempted to remove primary calendar from list\n - 404: Not Found - Calendar not found in user's list\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Unique calendar identifier (UUID)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "watch_calendar_list",
+ "description": "Watch for changes to CalendarList resources.\n \n Sets up webhook notifications (Channel) for changes to the user's calendar list.\n Monitors for additions, removals, and updates to calendar list entries.\n \n Request Body (Channel):\n - id: Required. Unique channel identifier for this watch\n - type: Channel type (only \"web_hook\" (or \"webhook\") supported)\n - address: Required. HTTPS URL where notifications will be sent\n - token: Optional. Verification token for webhook security\n \n Webhook Notifications (simplified):\n - Server will send POST requests to the specified address\n - Notifications triggered by calendar list changes:\n * Calendar added to or removed from list\n * Calendar list entry settings updated\n * Calendar permissions changed\n \n Channel Response:\n - Returns Channel object with fields: kind, id, resourceId, resourceUri, token, expiration, type, address\n - resourceUri is the collection path: /users/me/calendarList\n - resourceId is generated by the server\n\n Channel Management:\n - Each watch creates a unique notification channel\n - Channels can expire (set expiration time)\n - Multiple channels can watch the same resource\n - Use unique channel IDs to avoid conflicts\n \n Response Structure:\n - Returns Channel resource with Google Calendar API v3 format:\n * kind: \"api#channel\"\n * id: Channel identifier\n * resourceId: Resource being watched\n * resourceUri: Resource URI path\n * token: Verification token (if provided)\n * expiration: Channel expiration time (if set)\n * type: Channel type \"web_hook\" (or \"webhook\").\n * address: Notification delivery address\n \n Status Codes:\n - 200: Success - Watch channel created successfully\n - 400: Bad Request - Invalid channel configuration or query parameters\n - 500: Internal Server Error\n \n Note: This is a simplified implementation. In production, you would need:\n - Webhook endpoint verification\n - Channel management and cleanup\n - Actual change detection and notification dispatch",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique channel identifier for this watch",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "description": "Channel type (only web_hook supported; 'webhook' accepted as alias)",
+ "enum": [
+ "web_hook",
+ "webhook"
+ ],
+ "default": "web_hook"
+ },
+ "address": {
+ "type": "string",
+ "description": "HTTPS URL where notifications will be sent",
+ "format": "uri",
+ "minLength": 1
+ },
+ "token": {
+ "type": "string",
+ "description": "Verification token for webhook security",
+ "maxLength": 256
+ },
+ "params": {
+ "type": "object",
+ "description": "Optional parameters (Google spec supports 'ttl' in seconds as string)",
+ "properties": {
+ "ttl": {
+ "type": "string",
+ "description": "Time to live in seconds (string). Server computes expiration = now + ttl"
+ }
+ }
+ }
+ },
+ "required": [
+ "id",
+ "type",
+ "address"
+ ]
+ }
+ },
+ {
+ "name": "list_events",
+ "description": "List events on the specified calendar.\n \n Returns events from a calendar following Google Calendar API v3 structure.\n Supports filtering by time range, search terms, and other parameters to retrieve relevant events.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier to list events from\n \n Optional Parameters:\n - eventTypes: Event types to return (string: default, birthday, focusTime, fromGmail, outOfOffice, workingLocation)\n - iCalUID: Specifies an event ID in the iCalendar format to retrieve (string)\n - maxAttendees: Maximum number of attendees to include in response (integer)\n - maxResults: Maximum number of events returned (1-2500, default 250)\n - orderBy: Order of events returned (startTime or updated)\n - pageToken: Token for pagination\n - privateExtendedProperty: Extended properties constraint for private properties (string, format: propertyName=value)\n - q: Text search terms to find events (mutually exclusive with iCalUID)\n - sharedExtendedProperty: Extended properties constraint for shared properties (string, format: propertyName=value)\n - showDeleted: Include deleted events (boolean)\n - showHiddenInvitations: Whether to include hidden invitations (boolean)\n - singleEvents: Expand recurring events into instances (boolean)\n - syncToken: Token for incremental sync\n - timeMax: Upper bound for event start time (RFC3339 timestamp)\n - timeMin: Lower bound for event start time (RFC3339 timestamp)\n - timeZone: Time zone used in the response (string, IANA timezone)\n - updatedMin: Lower bound for last modification time (RFC3339 timestamp)\n \n Response Structure:\n - Returns events collection with Google Calendar API v3 format:\n * kind: \"calendar#events\"\n * etag: ETag of the collection\n * items: Array of Event objects\n * nextPageToken: Token for next page (if applicable)\n * nextSyncToken: Token for incremental sync (if applicable)\n \n Status Codes:\n - 200: Success - Events retrieved successfully\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventTypes": {
+ "type": "string",
+ "description": "Event types to return. Possible values are: 'default' - Events that don't match any of the events below, 'outOfOffice' - Out of office events, 'focusTime' - Focus time events, 'workingLocation' - Working location events, 'fromGmail' - Events from Gmail (deprecated), 'birthday' - Birthday events. Optional. Multiple event types can be provided using repeated parameter instances"
+ },
+ "iCalUID": {
+ "type": "string",
+ "description": "Specifies an event ID in the iCalendar format to be provided in the response. Optional. Use this if you want to search for an event by its iCalendar ID. Mutually exclusive with q. Optional."
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional."
+ },
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of events returned on one result page. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.",
+ "minimum": 1,
+ "maximum": 2500
+ },
+ "orderBy": {
+ "type": "string",
+ "description": "The order of the events returned in the result. Optional. The default is an unspecified, stable order.",
+ "enum": [
+ "startTime",
+ "updated"
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Token specifying which result page to return. Optional."
+ },
+ "privateExtendedProperty": {
+ "type": "string",
+ "description": "Extended properties constraint specified as propertyName=value. Matches only private properties. This parameter might be repeated multiple times to return events that match all given constraints."
+ },
+ "q": {
+ "type": "string",
+ "description": "Free text search terms to find events that match these terms in any field, except for extended properties. Optional."
+ },
+ "sharedExtendedProperty": {
+ "type": "string",
+ "description": "Extended properties constraint specified as propertyName=value. Matches only shared properties. This parameter might be repeated multiple times to return events that match all given constraints."
+ },
+ "showDeleted": {
+ "type": "boolean",
+ "description": "Whether to include deleted events (with status equals 'cancelled') in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if showDeleted and singleEvents are both False. If showDeleted and singleEvents are both True, only single instances of deleted events (but not the underlying recurring events) are returned. Optional. The default is False."
+ },
+ "showHiddenInvitations": {
+ "type": "boolean",
+ "description": "Whether to include hidden invitations in the result. Optional. The default is False."
+ },
+ "singleEvents": {
+ "type": "boolean",
+ "description": "Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. Optional. The default is False."
+ },
+ "syncToken": {
+ "type": "string",
+ "description": "Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then. All events deleted since the previous list request will always be in the result set and it is not allowed to set showDeleted to False. There are several query parameters that cannot be specified together with nextSyncToken to ensure consistency of the client state."
+ },
+ "timeMax": {
+ "type": "string",
+ "description": "Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMin is set, timeMax must be greater than timeMin."
+ },
+ "timeMin": {
+ "type": "string",
+ "description": "Lower bound (exclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset, for example, 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but are ignored. If timeMax is set, timeMin must be less than timeMax."
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Time zone used in the response. Optional. The default is the time zone of the calendar."
+ },
+ "updatedMin": {
+ "type": "string",
+ "description": "Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showDeleted. Optional. The default is not to filter by last modification time."
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "create_event",
+ "description": "Create a new event in the specified calendar following Google Calendar API v3 specification.\n \n Creates a new event with full Google Calendar API v3 compatibility. Supports all standard event properties\n including attendees, attachments, conference data, reminders, and event type-specific properties.\n \n Required Properties:\n - calendarId: Calendar identifier where event will be created\n - end: Event end time (dateTime/date object with optional timeZone)\n - start: Event start time (dateTime/date object with optional timeZone)\n \n Optional Properties (Google Calendar API v3 compliant):\n - attachments: File attachments for the event\n - attendees: List of event attendees with email, displayName, responseStatus\n - colorId: Color ID of the event (1-11 for event colors)\n - conferenceData: Conference/meeting data for video calls\n - description: Event description text\n - eventType: Event type (default, outOfOffice, focusTime, workingLocation)\n - extendedProperties: Private and shared extended properties\n - focusTimeProperties: Focus time properties for focusTime events\n - guestsCanInviteOthers: Whether guests can invite others\n - guestsCanModify: Whether guests can modify the event\n - guestsCanSeeOtherGuests: Whether guests can see other guests\n - hangoutLink: Hangout video call link\n - iCalUID: iCalendar UID for external integration\n - location: Geographic location of the event\n - locked: Whether the event is locked against changes\n - originalStartTime: Original start time for recurring event instances (must match start values)\n - outOfOfficeProperties: Out of office properties for outOfOffice events\n - privateCopy: Whether this is a private copy of the event\n - recurrence: List of RRULE, EXRULE, RDATE and EXDATE lines\n - reminders: Reminder settings with useDefault and overrides\n - sequence: iCalendar sequence number\n - source: Source from which the event was created\n - status: Event status (confirmed, tentative, cancelled)\n - summary: Event title/summary\n - transparency: Whether event blocks time (opaque, transparent)\n - visibility: Event visibility (default, public, private, confidential)\n - workingLocationProperties: Working location properties for workingLocation events\n \n Query Parameters:\n - conferenceDataVersion: Conference data version supported (0-1)\n - maxAttendees: Maximum number of attendees to include in response\n - sendUpdates: Guests who should receive notifications (all, externalOnly, none)\n - supportsAttachments: Whether client supports event attachments\n \n Response Structure:\n - Returns created event with complete Google Calendar API v3 format\n - Includes generated event ID, timestamps, and all provided properties\n - Attendees list may be limited by maxAttendees parameter\n \n Status Codes:\n - 201: Created - Event created successfully\n - 400: Bad Request - Invalid event data or missing required fields\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier where event will be created"
+ },
+ "end": {
+ "type": "object",
+ "description": "Event end time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "start": {
+ "type": "object",
+ "description": "Event start time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "attachments": {
+ "type": "array",
+ "description": "File attachments for the event",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fileUrl": {
+ "type": "string",
+ "description": "URL of attached file"
+ }
+ },
+ "required": [
+ "fileUrl"
+ ]
+ }
+ },
+ "attendees": {
+ "type": "array",
+ "description": "List of event attendees",
+ "items": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Attendee email address"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Attendee display name"
+ },
+ "optional": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendee is optional"
+ },
+ "resource": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendee is a resource"
+ },
+ "responseStatus": {
+ "type": "string",
+ "description": "Response status: needsAction, declined, tentative, accepted"
+ },
+ "comment": {
+ "type": "string",
+ "description": "Attendee comment"
+ },
+ "additionalGuests": {
+ "type": "integer",
+ "description": "Number of additional guests"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ }
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Color ID of the event (1-11 for event colors)"
+ },
+ "conferenceData": {
+ "type": "object",
+ "description": "Conference/meeting data for video calls",
+ "properties": {
+ "conferenceId": {
+ "type": "string",
+ "description": "Conference ID"
+ },
+ "conferenceSolution": {
+ "type": "object",
+ "description": "Conference solution details",
+ "properties": {
+ "iconUri": {
+ "type": "string",
+ "description": "Icon URI for the conference solution"
+ },
+ "key": {
+ "type": "object",
+ "description": "Conference solution key",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution type"
+ }
+ }
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the conference solution"
+ }
+ }
+ },
+ "createRequest": {
+ "type": "object",
+ "description": "Conference create request details",
+ "properties": {
+ "conferenceSolutionKey": {
+ "type": "object",
+ "description": "Conference solution for the create request",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution key type"
+ }
+ }
+ },
+ "requestId": {
+ "type": "string",
+ "description": "Request ID for creating the conference"
+ }
+ }
+ },
+ "entryPoints": {
+ "type": "array",
+ "description": "Conference entry points",
+ "items": {
+ "type": "object",
+ "properties": {
+ "accessCode": {
+ "type": "string",
+ "description": "Access code for the conference"
+ },
+ "entryPointType": {
+ "type": "string",
+ "description": "Type of entry point"
+ },
+ "label": {
+ "type": "string",
+ "description": "Label for the entry point"
+ },
+ "meetingCode": {
+ "type": "string",
+ "description": "Meeting code for the conference"
+ },
+ "passcode": {
+ "type": "string",
+ "description": "Passcode for the conference"
+ },
+ "password": {
+ "type": "string",
+ "description": "Password for the conference"
+ },
+ "pin": {
+ "type": "string",
+ "description": "PIN for the conference"
+ },
+ "uri": {
+ "type": "string",
+ "description": "URI for the conference entry point"
+ }
+ }
+ }
+ },
+ "notes": {
+ "type": "string",
+ "description": "Conference notes"
+ },
+ "signature": {
+ "type": "string",
+ "description": "Conference signature"
+ }
+ }
+ },
+ "description": {
+ "type": "string",
+ "description": "Event description text"
+ },
+ "birthdayProperties": {
+ "type": "object",
+ "description": "Birthday properties for birthday events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "birthday"
+ ],
+ "description": "Type of birthday event, must be 'birthday'. Cannot be changed after event creation."
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "eventType": {
+ "type": "string",
+ "description": "Event type: default, birthday, outOfOffice, focusTime, workingLocation",
+ "enum": [
+ "default",
+ "birthday",
+ "outOfOffice",
+ "focusTime",
+ "workingLocation"
+ ]
+ },
+ "extendedProperties": {
+ "type": "object",
+ "description": "Extended properties",
+ "properties": {
+ "private": {
+ "type": "object",
+ "description": "Private extended properties"
+ },
+ "shared": {
+ "type": "object",
+ "description": "Shared extended properties"
+ }
+ }
+ },
+ "focusTimeProperties": {
+ "type": "object",
+ "description": "Focus time properties for focusTime events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "chatStatus": {
+ "type": "string",
+ "description": "The status to mark the user in Chat and related products",
+ "enum": [
+ "available",
+ "doNotDisturb"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "guestsCanInviteOthers": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can invite others"
+ },
+ "guestsCanModify": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether guests can modify the event"
+ },
+ "guestsCanSeeOtherGuests": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can see other guests"
+ },
+ "iCalUID": {
+ "type": "string",
+ "description": "iCalendar UID for external integration"
+ },
+ "location": {
+ "type": "string",
+ "description": "Geographic location of the event"
+ },
+ "originalStartTime": {
+ "type": "object",
+ "description": "Original start time for recurring event instances (must match start field values)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "outOfOfficeProperties": {
+ "type": "object",
+ "description": "Out of office properties for outOfOffice events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "recurrence": {
+ "type": "array",
+ "description": "List of RRULE, EXRULE, RDATE and EXDATE lines for recurring events following RFC 5545 (iCalendar) standard.\n \n Supported Recurrence Types:\n \n RRULE (Recurrence Rule) - Defines the pattern for recurring events:\n \u2022 FREQ: Frequency (DAILY, WEEKLY, MONTHLY, YEARLY)\n \u2022 INTERVAL: Interval between occurrences (e.g., INTERVAL=2 for every 2 weeks)\n \u2022 COUNT: Maximum number of occurrences\n \u2022 UNTIL: End date (format: YYYYMMDDTHHMMSSZ)\n \u2022 BYDAY: Days of week (MO, TU, WE, TH, FR, SA, SU)\n \u2022 BYMONTHDAY: Days of month (1-31)\n \u2022 BYMONTH: Months (1-12)\n \u2022 BYSETPOS: Position in set (e.g., 1st, 2nd, -1 for last)\n \n EXDATE (Exception Dates) - Exclude specific occurrences:\n \u2022 Format: EXDATE:YYYYMMDDTHHMMSSZ or EXDATE;VALUE=DATE:YYYYMMDD\n \u2022 Use timezone format for timed events, date format for all-day events\n \n RDATE (Recurrence Dates) - Add specific occurrences:\n \u2022 Format: RDATE:YYYYMMDDTHHMMSSZ or RDATE;VALUE=DATE:YYYYMMDD\n \n Common Examples:\n \u2022 Daily: [\"RRULE:FREQ=DAILY\"]\n \u2022 Every weekday: [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"]\n \u2022 Weekly on specific days: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"]\n \u2022 Monthly on specific date: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=15\"]\n \u2022 First Monday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=1MO\"]\n \u2022 Last Friday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=-1FR\"]\n \u2022 Yearly: [\"RRULE:FREQ=YEARLY\"]\n \u2022 Every 2 weeks: [\"RRULE:FREQ=WEEKLY;INTERVAL=2\"]\n \u2022 10 times only: [\"RRULE:FREQ=WEEKLY;COUNT=10\"]\n \u2022 Until specific date: [\"RRULE:FREQ=DAILY;UNTIL=20231231T235959Z\"]\n \n Complex Examples:\n \u2022 Weekly with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\", \"EXDATE:20231024T100000Z\"]\n \u2022 Monthly with additional dates: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=1\", \"RDATE:20231215T100000Z\"]\n \u2022 Every other month on 2nd Tuesday: [\"RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=2TU\"]\n \n All-Day Event Examples:\n \u2022 Daily all-day: [\"RRULE:FREQ=DAILY\"]\n \u2022 Weekly all-day with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=MO\", \"EXDATE;VALUE=DATE:20231030\"]\n \n Note: For all-day events, use VALUE=DATE format for EXDATE/RDATE. For timed events, use full timestamp format.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reminders": {
+ "type": "object",
+ "description": "Reminder settings",
+ "properties": {
+ "useDefault": {
+ "type": "boolean",
+ "description": "Whether to use default reminders"
+ },
+ "overrides": {
+ "type": "array",
+ "description": "Custom reminder overrides",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ],
+ "description": "Reminder method"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event"
+ }
+ },
+ "required": [
+ "method",
+ "minutes"
+ ]
+ }
+ }
+ }
+ },
+ "sequence": {
+ "type": "integer",
+ "description": "iCalendar sequence number"
+ },
+ "source": {
+ "type": "object",
+ "description": "Source from which the event was created",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "Source URL"
+ },
+ "title": {
+ "type": "string",
+ "description": "Source title"
+ }
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "Event status: confirmed, tentative, cancelled",
+ "enum": [
+ "confirmed",
+ "tentative",
+ "cancelled"
+ ]
+ },
+ "summary": {
+ "type": "string",
+ "description": "Event title/summary"
+ },
+ "transparency": {
+ "type": "string",
+ "description": "Whether event blocks time: opaque, transparent",
+ "enum": [
+ "opaque",
+ "transparent"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Event visibility: default, public, private, confidential",
+ "enum": [
+ "default",
+ "public",
+ "private",
+ "confidential"
+ ]
+ },
+ "workingLocationProperties": {
+ "type": "object",
+ "description": "Working location properties for workingLocation events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "homeOffice",
+ "officeLocation",
+ "customLocation"
+ ],
+ "description": "Type of the working location. Required when adding working location properties"
+ },
+ "customLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from a custom location",
+ "properties": {
+ "label": {
+ "type": "string",
+ "description": "An optional extra label for additional information"
+ }
+ }
+ },
+ "homeOffice": {
+ "type": "object",
+ "description": "If present, specifies that the user is working at home",
+ "properties": {
+ "address_1": {
+ "type": "string",
+ "description": "Home Office address 1"
+ },
+ "address_2": {
+ "type": "string",
+ "description": "Home Office address 2"
+ },
+ "city": {
+ "type": "string",
+ "description": "City located"
+ },
+ "state": {
+ "type": "string",
+ "description": "State of the home office"
+ },
+ "postal_code": {
+ "type": "string",
+ "description": "Postal code of the home office"
+ }
+ },
+ "additionalProperties": true
+ },
+ "officeLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from an office",
+ "properties": {
+ "buildingId": {
+ "type": "string",
+ "description": "An optional building identifier. This should reference a building ID in the organization's Resources database"
+ },
+ "deskId": {
+ "type": "string",
+ "description": "An optional desk identifier"
+ },
+ "floorId": {
+ "type": "string",
+ "description": "An optional floor identifier"
+ },
+ "floorSectionId": {
+ "type": "string",
+ "description": "An optional floor section identifier"
+ },
+ "label": {
+ "type": "string",
+ "description": "The office name that's displayed in Calendar Web and Mobile clients. We recommend you reference a building name in the organization's Resources database"
+ }
+ }
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "conferenceDataVersion": {
+ "type": "integer",
+ "description": "Conference data version supported (0-1)",
+ "minimum": 0,
+ "maximum": 1
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "Maximum number of attendees to include in response"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications: all, externalOnly, none",
+ "enum": [
+ "all",
+ "externalOnly",
+ "none"
+ ]
+ },
+ "supportsAttachments": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether client supports event attachments"
+ }
+ },
+ "required": [
+ "calendarId",
+ "end",
+ "start"
+ ]
+ }
+ },
+ {
+ "name": "get_event",
+ "description": "Retrieve a specific event by its ID from the specified calendar.\n \n Returns event details following Google Calendar API v3 structure.\n Provides complete event information including attendees, reminders, and recurrence settings.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier\n - eventId: Required. Event identifier\n - timeZone: Optional. Time zone for returned times (IANA timezone)\n \n Response Structure:\n - Returns event with Google Calendar API v3 format:\n * kind: \"calendar#event\"\n * etag: ETag of the resource\n * id: Unique event identifier\n * summary: Event title\n * description: Event description (if present)\n * location: Event location (if present)\n * start: Event start time with timezone\n * end: Event end time with timezone\n * recurrence: Recurrence rules (if recurring)\n * status: Event status\n * visibility: Event visibility\n * attendees: List of attendees (if present)\n * reminders: Reminder settings\n \n Status Codes:\n - 200: Success - Event retrieved successfully\n - 404: Not Found - Event or calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Event identifier"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Time zone for returned times (IANA timezone)"
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "Maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional."
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId"
+ ]
+ }
+ },
+ {
+ "name": "patch_event",
+ "description": "Partially update an event (only specified fields are modified) following Google Calendar API v3.\n \n Updates an event with partial data using Google Calendar API v3 structure.\n Only provided fields will be updated, others remain unchanged.\n Use for incremental updates without affecting other event properties.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier\n - eventId: Required. Event identifier\n \n Optional Update Fields (Google Calendar API v3 compliant):\n - attachments: File attachments for the event\n - attendees: List of event attendees with email, displayName, responseStatus\n - colorId: Color ID of the event (1-11 for event colors)\n - conferenceData: Conference/meeting data for video calls\n - description: Event description text\n - end: Event end time (dateTime/date object with optional timeZone)\n - eventType: Event type (default, outOfOffice, focusTime, workingLocation)\n - extendedProperties: Private and shared extended properties\n - focusTimeProperties: Focus time properties for focusTime events\n - guestsCanInviteOthers: Whether guests can invite others\n - guestsCanModify: Whether guests can modify the event\n - guestsCanSeeOtherGuests: Whether guests can see other guests\n - hangoutLink: Hangout video call link\n - iCalUID: iCalendar UID for external integration\n - location: Geographic location of the event\n - locked: Whether the event is locked against changes\n - outOfOfficeProperties: Out of office properties for outOfOffice events\n - privateCopy: Whether this is a private copy of the event\n - recurrence: List of RRULE, EXRULE, RDATE and EXDATE lines\n - reminders: Reminder settings with useDefault and overrides\n - sequence: iCalendar sequence number\n - source: Source from which the event was created\n - start: Event start time (dateTime/date object with optional timeZone)\n - status: Event status (confirmed, tentative, cancelled)\n - summary: Event title/summary\n - transparency: Whether event blocks time (opaque, transparent)\n - visibility: Event visibility (default, public, private, confidential)\n - workingLocationProperties: Working location properties for workingLocation events\n \n Query Parameters:\n - sendUpdates: Guests who should receive notifications (all, externalOnly, none)\n \n Partial Update Behavior:\n - Only fields provided in request body are updated\n - Missing fields are left unchanged\n - At least one field should be provided for update\n \n Response Structure:\n - Returns updated event with Google Calendar API v3 format\n \n Status Codes:\n - 200: Success - Event updated successfully\n - 400: Bad Request - Invalid update data\n - 404: Not Found - Event or calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Event identifier"
+ },
+ "summary": {
+ "type": "string",
+ "description": "Event title"
+ },
+ "description": {
+ "type": "string",
+ "description": "Event description"
+ },
+ "location": {
+ "type": "string",
+ "description": "Event location"
+ },
+ "attachments": {
+ "type": "array",
+ "description": "File attachments for the event",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fileUrl": {
+ "type": "string",
+ "description": "URL of attached file"
+ }
+ }
+ }
+ },
+ "attendees": {
+ "type": "array",
+ "description": "List of event attendees",
+ "items": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Attendee email address"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Attendee display name"
+ },
+ "optional": {
+ "type": "boolean",
+ "description": "Whether attendee is optional"
+ },
+ "resource": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendee is a resource"
+ },
+ "responseStatus": {
+ "type": "string",
+ "description": "Response status"
+ },
+ "comment": {
+ "type": "string",
+ "description": "Attendee comment"
+ },
+ "additionalGuests": {
+ "type": "integer",
+ "description": "Number of additional guests"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ }
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Color ID of the event(1-11 for event colors)"
+ },
+ "conferenceData": {
+ "type": "object",
+ "description": "Conference/meeting data for video calls",
+ "properties": {
+ "conferenceId": {
+ "type": "string",
+ "description": "Conference ID"
+ },
+ "conferenceSolution": {
+ "type": "object",
+ "description": "Conference solution details",
+ "properties": {
+ "iconUri": {
+ "type": "string",
+ "description": "Icon URI for the conference solution"
+ },
+ "key": {
+ "type": "object",
+ "description": "Conference solution key",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution type"
+ }
+ }
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the conference solution"
+ }
+ }
+ },
+ "createRequest": {
+ "type": "object",
+ "description": "Conference create request details",
+ "properties": {
+ "conferenceSolutionKey": {
+ "type": "object",
+ "description": "Conference solution for the create request",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution key type"
+ }
+ }
+ },
+ "requestId": {
+ "type": "string",
+ "description": "Request ID for creating the conference"
+ }
+ }
+ },
+ "entryPoints": {
+ "type": "array",
+ "description": "Conference entry points",
+ "items": {
+ "type": "object",
+ "properties": {
+ "accessCode": {
+ "type": "string",
+ "description": "Access code for the conference"
+ },
+ "entryPointType": {
+ "type": "string",
+ "description": "Type of entry point"
+ },
+ "label": {
+ "type": "string",
+ "description": "Label for the entry point"
+ },
+ "meetingCode": {
+ "type": "string",
+ "description": "Meeting code for the conference"
+ },
+ "passcode": {
+ "type": "string",
+ "description": "Passcode for the conference"
+ },
+ "password": {
+ "type": "string",
+ "description": "Password for the conference"
+ },
+ "pin": {
+ "type": "string",
+ "description": "PIN for the conference"
+ },
+ "uri": {
+ "type": "string",
+ "description": "URI for the conference entry point"
+ }
+ }
+ }
+ },
+ "notes": {
+ "type": "string",
+ "description": "Conference notes"
+ },
+ "signature": {
+ "type": "string",
+ "description": "Conference signature"
+ }
+ }
+ },
+ "birthdayProperties": {
+ "type": "object",
+ "description": "Birthday properties for birthday events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "birthday"
+ ],
+ "description": "Type of birthday event, must be 'birthday'. Cannot be changed after event creation."
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "end": {
+ "type": "object",
+ "description": "Event end time",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone"
+ }
+ }
+ },
+ "eventType": {
+ "type": "string",
+ "description": "Event type",
+ "enum": [
+ "default",
+ "birthday",
+ "outOfOffice",
+ "focusTime",
+ "workingLocation"
+ ]
+ },
+ "extendedProperties": {
+ "type": "object",
+ "description": "Extended properties",
+ "properties": {
+ "private": {
+ "type": "object",
+ "description": "Private extended properties"
+ },
+ "shared": {
+ "type": "object",
+ "description": "Shared extended properties"
+ }
+ }
+ },
+ "focusTimeProperties": {
+ "type": "object",
+ "description": "Focus time properties for focusTime events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "chatStatus": {
+ "type": "string",
+ "description": "The status to mark the user in Chat and related products",
+ "enum": [
+ "available",
+ "doNotDisturb"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "guestsCanInviteOthers": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can invite others"
+ },
+ "guestsCanModify": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether guests can modify the event"
+ },
+ "guestsCanSeeOtherGuests": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can see other guests"
+ },
+ "hangoutLink": {
+ "type": "string",
+ "description": "Hangout link"
+ },
+ "iCalUID": {
+ "type": "string",
+ "description": "iCalendar UID"
+ },
+ "outOfOfficeProperties": {
+ "type": "object",
+ "description": "Out of office properties for outOfOffice events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "locked": {
+ "type": "boolean",
+ "description": "Whether event is locked"
+ },
+ "privateCopy": {
+ "type": "boolean",
+ "description": "Whether this is a private copy"
+ },
+ "recurrence": {
+ "type": "array",
+ "description": "List of RRULE, EXRULE, RDATE and EXDATE lines for recurring events following RFC 5545 (iCalendar) standard.\n \n Supported Recurrence Types:\n \n RRULE (Recurrence Rule) - Defines the pattern for recurring events:\n \u2022 FREQ: Frequency (DAILY, WEEKLY, MONTHLY, YEARLY)\n \u2022 INTERVAL: Interval between occurrences (e.g., INTERVAL=2 for every 2 weeks)\n \u2022 COUNT: Maximum number of occurrences\n \u2022 UNTIL: End date (format: YYYYMMDDTHHMMSSZ)\n \u2022 BYDAY: Days of week (MO, TU, WE, TH, FR, SA, SU)\n \u2022 BYMONTHDAY: Days of month (1-31)\n \u2022 BYMONTH: Months (1-12)\n \u2022 BYSETPOS: Position in set (e.g., 1st, 2nd, -1 for last)\n \n EXDATE (Exception Dates) - Exclude specific occurrences:\n \u2022 Format: EXDATE:YYYYMMDDTHHMMSSZ or EXDATE;VALUE=DATE:YYYYMMDD\n \u2022 Use timezone format for timed events, date format for all-day events\n \n RDATE (Recurrence Dates) - Add specific occurrences:\n \u2022 Format: RDATE:YYYYMMDDTHHMMSSZ or RDATE;VALUE=DATE:YYYYMMDD\n \n Common Examples:\n \u2022 Daily: [\"RRULE:FREQ=DAILY\"]\n \u2022 Every weekday: [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"]\n \u2022 Weekly on specific days: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"]\n \u2022 Monthly on specific date: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=15\"]\n \u2022 First Monday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=1MO\"]\n \u2022 Last Friday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=-1FR\"]\n \u2022 Yearly: [\"RRULE:FREQ=YEARLY\"]\n \u2022 Every 2 weeks: [\"RRULE:FREQ=WEEKLY;INTERVAL=2\"]\n \u2022 10 times only: [\"RRULE:FREQ=WEEKLY;COUNT=10\"]\n \u2022 Until specific date: [\"RRULE:FREQ=DAILY;UNTIL=20231231T235959Z\"]\n \n Complex Examples:\n \u2022 Weekly with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\", \"EXDATE:20231024T100000Z\"]\n \u2022 Monthly with additional dates: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=1\", \"RDATE:20231215T100000Z\"]\n \u2022 Every other month on 2nd Tuesday: [\"RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=2TU\"]\n \n All-Day Event Examples:\n \u2022 Daily all-day: [\"RRULE:FREQ=DAILY\"]\n \u2022 Weekly all-day with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=MO\", \"EXDATE;VALUE=DATE:20231030\"]\n \n Note: For all-day events, use VALUE=DATE format for EXDATE/RDATE. For timed events, use full timestamp format.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reminders": {
+ "type": "object",
+ "description": "Reminder settings",
+ "properties": {
+ "useDefault": {
+ "type": "boolean",
+ "description": "Whether to use default reminders"
+ },
+ "overrides": {
+ "type": "array",
+ "description": "Custom reminder overrides",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ],
+ "description": "Reminder method"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event"
+ }
+ },
+ "required": [
+ "method",
+ "minutes"
+ ]
+ }
+ }
+ }
+ },
+ "sequence": {
+ "type": "integer",
+ "description": "Sequence number"
+ },
+ "source": {
+ "type": "object",
+ "description": "Source from which the event was created",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "Source URL"
+ },
+ "title": {
+ "type": "string",
+ "description": "Source title"
+ }
+ }
+ },
+ "start": {
+ "type": "object",
+ "description": "Event start time",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone"
+ }
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "Event status: confirmed, tentative, cancelled",
+ "enum": [
+ "confirmed",
+ "tentative",
+ "cancelled"
+ ]
+ },
+ "transparency": {
+ "type": "string",
+ "description": "Event transparency",
+ "enum": [
+ "opaque",
+ "transparent"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Event visibility",
+ "enum": [
+ "default",
+ "public",
+ "private",
+ "confidential"
+ ]
+ },
+ "workingLocationProperties": {
+ "type": "object",
+ "description": "Working location properties for workingLocation events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "homeOffice",
+ "officeLocation",
+ "customLocation"
+ ],
+ "description": "Type of the working location. Required when adding working location properties"
+ },
+ "customLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from a custom location",
+ "properties": {
+ "label": {
+ "type": "string",
+ "description": "An optional extra label for additional information"
+ }
+ }
+ },
+ "homeOffice": {
+ "type": "object",
+ "description": "If present, specifies that the user is working at home",
+ "properties": {
+ "address_1": {
+ "type": "string",
+ "description": "Home Office address 1"
+ },
+ "address_2": {
+ "type": "string",
+ "description": "Home Office address 2"
+ },
+ "city": {
+ "type": "string",
+ "description": "City located"
+ },
+ "state": {
+ "type": "string",
+ "description": "State of the home office"
+ },
+ "postal_code": {
+ "type": "string",
+ "description": "Postal code of the home office"
+ }
+ },
+ "additionalProperties": true
+ },
+ "officeLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from an office",
+ "properties": {
+ "buildingId": {
+ "type": "string",
+ "description": "An optional building identifier. This should reference a building ID in the organization's Resources database"
+ },
+ "deskId": {
+ "type": "string",
+ "description": "An optional desk identifier"
+ },
+ "floorId": {
+ "type": "string",
+ "description": "An optional floor identifier"
+ },
+ "floorSectionId": {
+ "type": "string",
+ "description": "An optional floor section identifier"
+ },
+ "label": {
+ "type": "string",
+ "description": "The office name that's displayed in Calendar Web and Mobile clients. We recommend you reference a building name in the organization's Resources database"
+ }
+ }
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "conferenceDataVersion": {
+ "type": "integer",
+ "description": "Conference data version supported (0-1)",
+ "minimum": 0,
+ "maximum": 1
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "Maximum number of attendees to include in response"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications",
+ "enum": [
+ "all",
+ "externalOnly",
+ "none"
+ ]
+ },
+ "supportsAttachments": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether client supports event attachments"
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId"
+ ]
+ }
+ },
+ {
+ "name": "update_event",
+ "description": "Fully update an event (complete replacement) following Google Calendar API v3 specification.\n \n Updates an event following Google Calendar API v3 structure. This method does not support patch\n semantics and always updates the entire event resource. To do a partial update, perform a get\n followed by an update using etags to ensure atomicity.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier\n - eventId: Required. Event identifier\n - start: Required. Event start time (dateTime/date object with optional timeZone)\n - end: Required. Event end time (dateTime/date object with optional timeZone)\n \n Optional Properties (Google Calendar API v3 compliant):\n - attachments: File attachments for the event\n - attendees: List of event attendees with email, displayName, responseStatus\n - birthdayProperties: Birthday properties for birthday events\n - colorId: Color ID of the event (1-11 for event colors)\n - conferenceData: Conference/meeting data for video calls\n - description: Event description text\n - extendedProperties: Private and shared extended properties\n - focusTimeProperties: Focus time properties for focusTime events\n - guestsCanInviteOthers: Whether guests can invite others\n - guestsCanModify: Whether guests can modify the event\n - guestsCanSeeOtherGuests: Whether guests can see other guests\n - hangoutLink: Hangout video call link\n - iCalUID: iCalendar UID for external integration\n - location: Geographic location of the event\n - locked: Whether the event is locked against changes\n - outOfOfficeProperties: Out of office properties for outOfOffice events\n - privateCopy: Whether this is a private copy of the event\n - recurrence: List of RRULE, EXRULE, RDATE and EXDATE lines\n - reminders: Reminder settings with useDefault and overrides\n - sequence: iCalendar sequence number\n - source: Source from which the event was created\n - status: Event status (confirmed, tentative, cancelled)\n - summary: Event title/summary\n - transparency: Whether event blocks time (opaque, transparent)\n - visibility: Event visibility (default, public, private, confidential)\n - workingLocationProperties: Working location properties for workingLocation events\n \n Query Parameters:\n - conferenceDataVersion: Conference data version supported (0-1)\n - maxAttendees: Maximum number of attendees to include in response\n - sendUpdates: Guests who should receive notifications (all, externalOnly, none)\n - supportsAttachments: Whether client supports event attachments\n \n Full Update Behavior:\n - All fields are replaced (full replacement operation)\n - Missing optional fields are set to null/defaults\n - start and end are required for PUT operations\n - This is different from PATCH which only updates provided fields\n \n Response Structure:\n - Returns updated event with complete Google Calendar API v3 format\n \n Status Codes:\n - 200: Success - Event updated successfully\n - 400: Bad Request - Invalid update data or missing required fields\n - 404: Not Found - Event or calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Event identifier"
+ },
+ "start": {
+ "type": "object",
+ "description": "Event start time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "end": {
+ "type": "object",
+ "description": "Event end time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "summary": {
+ "type": "string",
+ "description": "Event title/summary"
+ },
+ "description": {
+ "type": "string",
+ "description": "Event description"
+ },
+ "location": {
+ "type": "string",
+ "description": "Event location"
+ },
+ "attachments": {
+ "type": "array",
+ "description": "File attachments for the event",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fileUrl": {
+ "type": "string",
+ "description": "URL of attached file"
+ }
+ }
+ }
+ },
+ "attendees": {
+ "type": "array",
+ "description": "List of event attendees",
+ "items": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Attendee email address"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Attendee display name"
+ },
+ "optional": {
+ "type": "boolean",
+ "description": "Whether attendee is optional"
+ },
+ "resource": {
+ "type": "boolean",
+ "description": "Whether attendee is a resource"
+ },
+ "responseStatus": {
+ "type": "string",
+ "description": "Response status"
+ },
+ "comment": {
+ "type": "string",
+ "description": "Attendee comment"
+ },
+ "additionalGuests": {
+ "type": "integer",
+ "description": "Number of additional guests"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ }
+ },
+ "eventType": {
+ "type": "string",
+ "description": "Event type",
+ "enum": [
+ "default",
+ "birthday",
+ "outOfOffice",
+ "focusTime",
+ "workingLocation"
+ ]
+ },
+ "birthdayProperties": {
+ "type": "object",
+ "description": "Birthday properties for birthday events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "birthday"
+ ],
+ "description": "Type of birthday event, must be 'birthday'. Cannot be changed after event creation."
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Color ID of the event"
+ },
+ "conferenceData": {
+ "type": "object",
+ "description": "Conference/meeting data for video calls",
+ "properties": {
+ "conferenceId": {
+ "type": "string",
+ "description": "Conference ID"
+ },
+ "conferenceSolution": {
+ "type": "object",
+ "description": "Conference solution details",
+ "properties": {
+ "iconUri": {
+ "type": "string",
+ "description": "Icon URI for the conference solution"
+ },
+ "key": {
+ "type": "object",
+ "description": "Conference solution key",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution type"
+ }
+ }
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the conference solution"
+ }
+ }
+ },
+ "createRequest": {
+ "type": "object",
+ "description": "Conference create request details",
+ "properties": {
+ "conferenceSolutionKey": {
+ "type": "object",
+ "description": "Conference solution for the create request",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Conference solution key type"
+ }
+ }
+ },
+ "requestId": {
+ "type": "string",
+ "description": "Request ID for creating the conference"
+ }
+ }
+ },
+ "entryPoints": {
+ "type": "array",
+ "description": "Conference entry points",
+ "items": {
+ "type": "object",
+ "properties": {
+ "accessCode": {
+ "type": "string",
+ "description": "Access code for the conference"
+ },
+ "entryPointType": {
+ "type": "string",
+ "description": "Type of entry point"
+ },
+ "label": {
+ "type": "string",
+ "description": "Label for the entry point"
+ },
+ "meetingCode": {
+ "type": "string",
+ "description": "Meeting code for the conference"
+ },
+ "passcode": {
+ "type": "string",
+ "description": "Passcode for the conference"
+ },
+ "password": {
+ "type": "string",
+ "description": "Password for the conference"
+ },
+ "pin": {
+ "type": "string",
+ "description": "PIN for the conference"
+ },
+ "uri": {
+ "type": "string",
+ "description": "URI for the conference entry point"
+ }
+ }
+ }
+ },
+ "notes": {
+ "type": "string",
+ "description": "Conference notes"
+ },
+ "signature": {
+ "type": "string",
+ "description": "Conference signature"
+ }
+ }
+ },
+ "extendedProperties": {
+ "type": "object",
+ "description": "Extended properties",
+ "properties": {
+ "private": {
+ "type": "object",
+ "description": "Private extended properties"
+ },
+ "shared": {
+ "type": "object",
+ "description": "Shared extended properties"
+ }
+ }
+ },
+ "focusTimeProperties": {
+ "type": "object",
+ "description": "Focus time properties for focusTime events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "chatStatus": {
+ "type": "string",
+ "description": "The status to mark the user in Chat and related products",
+ "enum": [
+ "available",
+ "doNotDisturb"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "guestsCanInviteOthers": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can invite others"
+ },
+ "guestsCanModify": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether guests can modify the event"
+ },
+ "guestsCanSeeOtherGuests": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether guests can see other guests"
+ },
+ "hangoutLink": {
+ "type": "string",
+ "description": "Hangout link"
+ },
+ "iCalUID": {
+ "type": "string",
+ "description": "iCalendar UID"
+ },
+ "locked": {
+ "type": "boolean",
+ "description": "Whether event is locked"
+ },
+ "outOfOfficeProperties": {
+ "type": "object",
+ "description": "Out of office properties for outOfOffice events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "privateCopy": {
+ "type": "boolean",
+ "description": "Whether this is a private copy"
+ },
+ "recurrence": {
+ "type": "array",
+ "description": "List of RRULE, EXRULE, RDATE and EXDATE lines for recurring events following RFC 5545 (iCalendar) standard.\n \n Supported Recurrence Types:\n \n RRULE (Recurrence Rule) - Defines the pattern for recurring events:\n \u2022 FREQ: Frequency (DAILY, WEEKLY, MONTHLY, YEARLY)\n \u2022 INTERVAL: Interval between occurrences (e.g., INTERVAL=2 for every 2 weeks)\n \u2022 COUNT: Maximum number of occurrences\n \u2022 UNTIL: End date (format: YYYYMMDDTHHMMSSZ)\n \u2022 BYDAY: Days of week (MO, TU, WE, TH, FR, SA, SU)\n \u2022 BYMONTHDAY: Days of month (1-31)\n \u2022 BYMONTH: Months (1-12)\n \u2022 BYSETPOS: Position in set (e.g., 1st, 2nd, -1 for last)\n \n EXDATE (Exception Dates) - Exclude specific occurrences:\n \u2022 Format: EXDATE:YYYYMMDDTHHMMSSZ or EXDATE;VALUE=DATE:YYYYMMDD\n \u2022 Use timezone format for timed events, date format for all-day events\n \n RDATE (Recurrence Dates) - Add specific occurrences:\n \u2022 Format: RDATE:YYYYMMDDTHHMMSSZ or RDATE;VALUE=DATE:YYYYMMDD\n \n Common Examples:\n \u2022 Daily: [\"RRULE:FREQ=DAILY\"]\n \u2022 Every weekday: [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"]\n \u2022 Weekly on specific days: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"]\n \u2022 Monthly on specific date: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=15\"]\n \u2022 First Monday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=1MO\"]\n \u2022 Last Friday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=-1FR\"]\n \u2022 Yearly: [\"RRULE:FREQ=YEARLY\"]\n \u2022 Every 2 weeks: [\"RRULE:FREQ=WEEKLY;INTERVAL=2\"]\n \u2022 10 times only: [\"RRULE:FREQ=WEEKLY;COUNT=10\"]\n \u2022 Until specific date: [\"RRULE:FREQ=DAILY;UNTIL=20231231T235959Z\"]\n \n Complex Examples:\n \u2022 Weekly with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\", \"EXDATE:20231024T100000Z\"]\n \u2022 Monthly with additional dates: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=1\", \"RDATE:20231215T100000Z\"]\n \u2022 Every other month on 2nd Tuesday: [\"RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=2TU\"]\n \n All-Day Event Examples:\n \u2022 Daily all-day: [\"RRULE:FREQ=DAILY\"]\n \u2022 Weekly all-day with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=MO\", \"EXDATE;VALUE=DATE:20231030\"]\n \n Note: For all-day events, use VALUE=DATE format for EXDATE/RDATE. For timed events, use full timestamp format.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reminders": {
+ "type": "object",
+ "description": "Reminder settings",
+ "properties": {
+ "useDefault": {
+ "type": "boolean",
+ "description": "Whether to use default reminders"
+ },
+ "overrides": {
+ "type": "array",
+ "description": "Custom reminder overrides",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ],
+ "description": "Reminder method"
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event"
+ }
+ },
+ "required": [
+ "method",
+ "minutes"
+ ]
+ }
+ }
+ }
+ },
+ "sequence": {
+ "type": "integer",
+ "description": "Sequence number"
+ },
+ "source": {
+ "type": "object",
+ "description": "Source from which the event was created",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "Source URL"
+ },
+ "title": {
+ "type": "string",
+ "description": "Source title"
+ }
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "Event status",
+ "enum": [
+ "confirmed",
+ "tentative",
+ "cancelled"
+ ]
+ },
+ "transparency": {
+ "type": "string",
+ "description": "Event transparency",
+ "enum": [
+ "opaque",
+ "transparent"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Event visibility",
+ "enum": [
+ "default",
+ "public",
+ "private",
+ "confidential"
+ ]
+ },
+ "workingLocationProperties": {
+ "type": "object",
+ "description": "Working location properties for workingLocation events",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "homeOffice",
+ "officeLocation",
+ "customLocation"
+ ],
+ "description": "Type of the working location. Required when adding working location properties"
+ },
+ "customLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from a custom location",
+ "properties": {
+ "label": {
+ "type": "string",
+ "description": "An optional extra label for additional information"
+ }
+ }
+ },
+ "homeOffice": {
+ "type": "object",
+ "description": "If present, specifies that the user is working at home",
+ "properties": {
+ "address_1": {
+ "type": "string",
+ "description": "Home Office address 1"
+ },
+ "address_2": {
+ "type": "string",
+ "description": "Home Office address 2"
+ },
+ "city": {
+ "type": "string",
+ "description": "City located"
+ },
+ "state": {
+ "type": "string",
+ "description": "State of the home office"
+ },
+ "postal_code": {
+ "type": "string",
+ "description": "Postal code of the home office"
+ }
+ },
+ "additionalProperties": true
+ },
+ "officeLocation": {
+ "type": "object",
+ "description": "If present, specifies that the user is working from an office",
+ "properties": {
+ "buildingId": {
+ "type": "string",
+ "description": "An optional building identifier. This should reference a building ID in the organization's Resources database"
+ },
+ "deskId": {
+ "type": "string",
+ "description": "An optional desk identifier"
+ },
+ "floorId": {
+ "type": "string",
+ "description": "An optional floor identifier"
+ },
+ "floorSectionId": {
+ "type": "string",
+ "description": "An optional floor section identifier"
+ },
+ "label": {
+ "type": "string",
+ "description": "The office name that's displayed in Calendar Web and Mobile clients. We recommend you reference a building name in the organization's Resources database"
+ }
+ }
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "conferenceDataVersion": {
+ "type": "integer",
+ "description": "Conference data version supported (0-1)",
+ "minimum": 0,
+ "maximum": 1
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "Maximum number of attendees to include in response"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications: all, externalOnly, none",
+ "enum": [
+ "all",
+ "externalOnly",
+ "none"
+ ]
+ },
+ "supportsAttachments": {
+ "type": "boolean",
+ "description": "Whether client supports event attachments"
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId",
+ "start",
+ "end"
+ ]
+ }
+ },
+ {
+ "name": "delete_event",
+ "description": "Delete an event from the specified calendar.\n \n Permanently deletes an event following Google Calendar API v3 behavior.\n This action cannot be undone. Use with caution.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier\n - eventId: Required. Event identifier to delete\n - sendUpdates: Optional. Guests who should receive notifications (all, externalOnly, none)\n \n Deletion Behavior:\n - Event is permanently removed from the calendar\n - This operation is irreversible\n - Notifications can be sent to attendees if specified\n \n Response Structure:\n - Returns 204 No Content on successful deletion\n - No response body as per Google Calendar API v3\n \n Status Codes:\n - 204: No Content - Event deleted successfully\n - 404: Not Found - Event or calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Event identifier to delete"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications: all, externalOnly, none"
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId"
+ ]
+ }
+ },
+ {
+ "name": "move_event",
+ "description": "Move an event from one calendar to another.\n \n Moves an event between calendars following Google Calendar API v3 behavior.\n The event retains its properties but changes calendar ownership.\n \n Request Body Requirements:\n - calendarId: Required. Source calendar identifier\n - eventId: Required. Event identifier to move\n - destination: Required. Target calendar identifier where event will be moved\n - sendUpdates: Optional. Guests who should receive notifications (all, externalOnly, none)\n \n Move Operation:\n - Event is transferred from source to destination calendar\n - Event properties (title, time, attendees, etc.) remain unchanged\n - Event ID may change during the move operation\n - Original event is removed from source calendar\n \n Response Structure:\n - Returns moved event with Google Calendar API v3 format\n - Event will have the same content but potentially new ID\n \n Status Codes:\n - 200: Success - Event moved successfully\n - 404: Not Found - Event, source calendar, or destination calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Source calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Event identifier to move"
+ },
+ "destination": {
+ "type": "string",
+ "description": "Target calendar identifier where event will be moved"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications: all, externalOnly, none"
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId",
+ "destination"
+ ]
+ }
+ },
+ {
+ "name": "quick_add_event",
+ "description": "Create an event using natural language text parsing.\n \n Creates an event from natural language text following Google Calendar API v3 structure.\n Automatically extracts date, time, and other details from the provided text.\n Similar to Quick Add feature in Google Calendar.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier where event will be created\n \n Required Query Parameters:\n - text: Required. Natural language text describing the event (e.g., 'Meeting tomorrow at 2pm')\n\n Request Body Requirements:\n - sendUpdates: Optional. Guests who should receive notifications (all, externalOnly, none)\n \n Text Parsing:\n - Automatically extracts event title from text\n - Identifies date and time information\n - Recognizes common patterns like 'tomorrow', 'next week', 'at 3pm'\n - May identify location if mentioned in text\n - Creates a properly formatted event from parsed information\n \n Response Structure:\n - Returns created event with Google Calendar API v3 format\n - Event will contain parsed information from the text\n \n Status Codes:\n - 201: Created - Event created successfully from text\n - 400: Bad Request - Unable to parse text or invalid calendar\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier where event will be created"
+ },
+ "text": {
+ "type": "string",
+ "description": "Natural language text describing the event (e.g., 'Meeting tomorrow at 2pm')"
+ },
+ "sendUpdates": {
+ "type": "string",
+ "description": "Guests who should receive notifications: all, externalOnly, none"
+ }
+ },
+ "required": [
+ "calendarId",
+ "text"
+ ]
+ }
+ },
+ {
+ "name": "import_event",
+ "description": "Import an event as a private copy to the specified calendar.\n \n This operation is used to add a private copy of an existing event to a calendar, following\n Google Calendar API v3 import specification. Supports comprehensive event data including\n type conversion, iCalUID handling, and attachment processing.\n \n Google Calendar API Import Features:\n - Creates a private copy of the event in the target calendar\n - Handles event type conversion (non-default types may be converted to default)\n - Manages iCalUID uniqueness and conflict resolution\n - Processes attendees, attachments, and conference data based on client capabilities\n - Supports all Google Calendar event types: default, birthday, focusTime, fromGmail, outOfOffice, workingLocation\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier where event will be imported\n - iCalUID: iCalendar UID for external calendar integration\n - start: Required. Event start time (dateTime or date with optional timeZone)\n - end: Required. Event end time (dateTime or date with optional timeZone)\n \n Advanced Import Properties:\n - attendees: Array of attendee objects with email, displayName, optional, responseStatus\n - conferenceData: Conference/meeting data (processed based on conferenceDataVersion)\n - attachments: File attachments (processed if supportsAttachments=true)\n - extendedProperties: Private and shared extended properties\n - focusTimeProperties: Focus time settings (for focusTime events)\n - outOfOfficeProperties: Out of office details (for outOfOffice events)\n - recurrence: Array of RRULE strings for recurring events\n - reminders: Reminder configuration with useDefault and overrides\n - source: Source information with title and URL\n - transparency: Event transparency (opaque/transparent)\n - visibility: Event visibility (default, public, private, confidential)\n - sequence: iCalendar sequence number\n - sequence: iCalendar sequence number\n - colorId: Color ID of the event (1-11 for event colors)\n - originalStartTime: Original start time for recurring event instances (must match start values)\n \n Query Parameters:\n - conferenceDataVersion: Conference data version support (0 or 1)\n - supportsAttachments: Whether client supports event attachments\n \n Import Processing:\n - Validates event data and user permissions\n - Converts unsupported event types to 'default' with warnings\n - Generates new event ID while preserving iCalUID if provided\n - Creates comprehensive event with all related objects (attendees, attachments, etc.)\n - Handles all-day events vs timed events automatically\n \n Response Structure:\n - Returns EventImportResponse with Google Calendar API v3 format:\n * Complete event data with generated IDs\n * Creator and organizer information\n * Conversion warnings if event type was changed\n * All imported properties and relationships\n \n Status Codes:\n - 201: Created - Event imported successfully as private copy\n - 400: Bad Request - Invalid import data or missing required fields\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier where event will be imported"
+ },
+ "summary": {
+ "type": "string",
+ "description": "Event title/summary (required)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Event description"
+ },
+ "location": {
+ "type": "string",
+ "description": "Event location"
+ },
+ "start": {
+ "type": "object",
+ "description": "Event start time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "end": {
+ "type": "object",
+ "description": "Event end time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "organizer": {
+ "type": "object",
+ "description": "The organizer of the event. If the organizer is also an attendee, this is indicated with a separate entry in attendees with the organizer field set to True. To change the organizer, use the move operation. Read-only, except when importing an event.",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "The organizer's email address. Must be a valid email address as per RFC5322."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "The organizer's name, if available."
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Event status: confirmed, tentative, cancelled",
+ "enum": [
+ "confirmed",
+ "tentative",
+ "cancelled"
+ ]
+ },
+ "transparency": {
+ "type": "string",
+ "description": "Event transparency: opaque, transparent",
+ "enum": [
+ "opaque",
+ "transparent"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Event visibility: default, public, private, confidential",
+ "enum": [
+ "default",
+ "public",
+ "private",
+ "confidential"
+ ]
+ },
+ "attendees": {
+ "type": "array",
+ "description": "Event attendees",
+ "items": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Attendee email address"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Attendee display name"
+ },
+ "optional": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendee is optional"
+ },
+ "resource": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendee is a resource"
+ },
+ "responseStatus": {
+ "type": "string",
+ "default": "needsAction",
+ "description": "Response status"
+ },
+ "comment": {
+ "type": "string",
+ "description": "Attendee comment"
+ },
+ "additionalGuests": {
+ "type": "integer",
+ "default": 0,
+ "description": "Number of additional guests"
+ }
+ },
+ "required": [
+ "email",
+ "responseStatus"
+ ]
+ }
+ },
+ "attendeesOmitted": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendees may have been omitted from the event's representation"
+ },
+ "colorId": {
+ "type": "string",
+ "description": "Color ID of the event (1-11 for event colors)"
+ },
+ "recurrence": {
+ "type": "array",
+ "description": "List of RRULE, EXRULE, RDATE and EXDATE lines for recurring events following RFC 5545 (iCalendar) standard.\n \n Supported Recurrence Types:\n \n RRULE (Recurrence Rule) - Defines the pattern for recurring events:\n \u2022 FREQ: Frequency (DAILY, WEEKLY, MONTHLY, YEARLY)\n \u2022 INTERVAL: Interval between occurrences (e.g., INTERVAL=2 for every 2 weeks)\n \u2022 COUNT: Maximum number of occurrences\n \u2022 UNTIL: End date (format: YYYYMMDDTHHMMSSZ)\n \u2022 BYDAY: Days of week (MO, TU, WE, TH, FR, SA, SU)\n \u2022 BYMONTHDAY: Days of month (1-31)\n \u2022 BYMONTH: Months (1-12)\n \u2022 BYSETPOS: Position in set (e.g., 1st, 2nd, -1 for last)\n \n EXDATE (Exception Dates) - Exclude specific occurrences:\n \u2022 Format: EXDATE:YYYYMMDDTHHMMSSZ or EXDATE;VALUE=DATE:YYYYMMDD\n \u2022 Use timezone format for timed events, date format for all-day events\n \n RDATE (Recurrence Dates) - Add specific occurrences:\n \u2022 Format: RDATE:YYYYMMDDTHHMMSSZ or RDATE;VALUE=DATE:YYYYMMDD\n \n Common Examples:\n \u2022 Daily: [\"RRULE:FREQ=DAILY\"]\n \u2022 Every weekday: [\"RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\"]\n \u2022 Weekly on specific days: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"]\n \u2022 Monthly on specific date: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=15\"]\n \u2022 First Monday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=1MO\"]\n \u2022 Last Friday of month: [\"RRULE:FREQ=MONTHLY;BYDAY=-1FR\"]\n \u2022 Yearly: [\"RRULE:FREQ=YEARLY\"]\n \u2022 Every 2 weeks: [\"RRULE:FREQ=WEEKLY;INTERVAL=2\"]\n \u2022 10 times only: [\"RRULE:FREQ=WEEKLY;COUNT=10\"]\n \u2022 Until specific date: [\"RRULE:FREQ=DAILY;UNTIL=20231231T235959Z\"]\n \n Complex Examples:\n \u2022 Weekly with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\", \"EXDATE:20231024T100000Z\"]\n \u2022 Monthly with additional dates: [\"RRULE:FREQ=MONTHLY;BYMONTHDAY=1\", \"RDATE:20231215T100000Z\"]\n \u2022 Every other month on 2nd Tuesday: [\"RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=2TU\"]\n \n All-Day Event Examples:\n \u2022 Daily all-day: [\"RRULE:FREQ=DAILY\"]\n \u2022 Weekly all-day with exceptions: [\"RRULE:FREQ=WEEKLY;BYDAY=MO\", \"EXDATE;VALUE=DATE:20231030\"]\n \n Note: For all-day events, use VALUE=DATE format for EXDATE/RDATE. For timed events, use full timestamp format.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "reminders": {
+ "type": "object",
+ "description": "Event reminders configuration",
+ "properties": {
+ "useDefault": {
+ "type": "boolean",
+ "description": "Whether to use default reminders"
+ },
+ "overrides": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "method": {
+ "type": "string",
+ "enum": [
+ "email",
+ "popup"
+ ]
+ },
+ "minutes": {
+ "type": "integer",
+ "description": "Minutes before event"
+ }
+ }
+ }
+ }
+ }
+ },
+ "attachments": {
+ "type": "array",
+ "description": "Event attachments (processed if supportsAttachments=true)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fileUrl": {
+ "type": "string",
+ "description": "URL of attached file"
+ }
+ },
+ "required": [
+ "fileUrl"
+ ]
+ }
+ },
+ "conferenceData": {
+ "type": "object",
+ "description": "Conference data (processed based on conferenceDataVersion)",
+ "properties": {
+ "createRequest": {
+ "type": "object",
+ "description": "Request to create conference"
+ },
+ "entryPoints": {
+ "type": "array",
+ "description": "Conference entry points",
+ "items": {
+ "type": "object",
+ "properties": {
+ "entryPointType": {
+ "type": "string",
+ "description": "Entry point type (video, phone, sip, more)"
+ },
+ "uri": {
+ "type": "string",
+ "description": "URI of the entry point"
+ },
+ "label": {
+ "type": "string",
+ "description": "Label for the entry point"
+ },
+ "pin": {
+ "type": "string",
+ "description": "PIN to access the conference"
+ },
+ "accessCode": {
+ "type": "string",
+ "description": "Access code for the conference"
+ },
+ "meetingCode": {
+ "type": "string",
+ "description": "Meeting code for the conference"
+ },
+ "passcode": {
+ "type": "string",
+ "description": "Passcode for the conference"
+ },
+ "password": {
+ "type": "string",
+ "description": "Password for the conference"
+ }
+ }
+ }
+ },
+ "conferenceSolution": {
+ "type": "object",
+ "description": "Conference solution details"
+ },
+ "conferenceId": {
+ "type": "string",
+ "description": "Conference ID"
+ },
+ "signature": {
+ "type": "string",
+ "description": "Conference signature"
+ }
+ }
+ },
+ "extendedProperties": {
+ "type": "object",
+ "description": "Extended properties",
+ "properties": {
+ "private": {
+ "type": "object",
+ "description": "Private extended properties"
+ },
+ "shared": {
+ "type": "object",
+ "description": "Shared extended properties"
+ }
+ }
+ },
+ "focusTimeProperties": {
+ "type": "object",
+ "description": "Focus time properties for focusTime events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "chatStatus": {
+ "type": "string",
+ "description": "The status to mark the user in Chat and related products",
+ "enum": [
+ "available",
+ "doNotDisturb"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "outOfOfficeProperties": {
+ "type": "object",
+ "description": "Out of office properties for outOfOffice events",
+ "properties": {
+ "autoDeclineMode": {
+ "type": "string",
+ "description": "Whether to decline meeting invitations which overlap Focus Time events",
+ "enum": [
+ "declineNone",
+ "declineAllConflictingInvitations",
+ "declineOnlyNewConflictingInvitations"
+ ]
+ },
+ "declineMessage": {
+ "type": "string",
+ "description": "Response message to set if an existing event or new invitation is automatically declined by Calendar"
+ }
+ }
+ },
+ "originalStartTime": {
+ "type": "object",
+ "description": "Original start time for event instances (must match start field values)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "RFC3339 timestamp with timezone for timed events"
+ },
+ "date": {
+ "type": "string",
+ "description": "Date in YYYY-MM-DD format for all-day events"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "IANA timezone identifier"
+ }
+ }
+ },
+ "source": {
+ "type": "object",
+ "description": "Event source information",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "Source URL"
+ },
+ "title": {
+ "type": "string",
+ "description": "Source title"
+ }
+ },
+ "required": [
+ "url",
+ "title"
+ ]
+ },
+ "iCalUID": {
+ "type": "string",
+ "description": "iCalendar UID for external calendar integration"
+ },
+ "sequence": {
+ "type": "integer",
+ "description": "iCalendar sequence number"
+ },
+ "guestsCanInviteOthers": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether attendees can invite others"
+ },
+ "guestsCanModify": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether attendees can modify the event"
+ },
+ "guestsCanSeeOtherGuests": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether attendees can see other guests"
+ },
+ "conferenceDataVersion": {
+ "type": "integer",
+ "description": "Version number of conference data supported by API client (0 or 1)"
+ },
+ "supportsAttachments": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether API client supports event attachments"
+ }
+ },
+ "required": [
+ "calendarId",
+ "start",
+ "end",
+ "iCalUID"
+ ]
+ }
+ },
+ {
+ "name": "get_event_instances",
+ "description": "Returns instances of the specified recurring event following Google Calendar API v3 specification.\n \n Returns individual instances of a recurring event with complete Google Calendar API v3 compatibility.\n Expands recurring events into their actual occurrences within the specified time range.\n Supports all official query parameters including filtering, pagination, and response formatting.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier\n - eventId: Required. Recurring event identifier\n \n Optional Parameters (Google Calendar API v3 compliant):\n - maxAttendees: The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.\n - maxResults: Maximum number of events returned on one result page. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.\n - originalStart: The original start time of the instance in the result. Optional.\n - pageToken: Token specifying which result page to return. Optional.\n - showDeleted: Whether to include deleted events (with status equals 'cancelled') in the result. Cancelled instances of recurring events will still be included if singleEvents is False. Optional.\n - timeMin: Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset.\n - timeMax: Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset.\n - timeZone: Time zone used in the response. Optional. The default is the time zone of the calendar.\n \n Instance Expansion Features:\n - Takes a recurring event and expands it into individual occurrences\n - Each instance shows the actual date/time it occurs\n - Useful for displaying recurring events in calendar views\n - Respects time range filters to limit results\n - Supports pagination for large recurring series\n - Handles timezone conversions based on timeZone parameter\n - Includes deleted instances when showDeleted=true\n \n Response Structure:\n - Returns events collection with Google Calendar API v3 format:\n * kind: \"calendar#events\"\n * etag: ETag of the collection\n * summary: Calendar summary\n * description: Calendar description\n * updated: Last modification time\n * timeZone: Response timezone\n * accessRole: User's access role\n * defaultReminders: Default reminders for the calendar\n * nextPageToken: Token for next page (if applicable)\n * items: Array of individual event instances\n \n Status Codes:\n - 200: Success - Event instances retrieved successfully\n - 400: Bad Request - Invalid parameters or non-recurring event\n - 403: Forbidden - Insufficient permissions\n - 404: Not Found - Event or calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier"
+ },
+ "eventId": {
+ "type": "string",
+ "description": "Recurring event identifier"
+ },
+ "maxAttendees": {
+ "type": "integer",
+ "description": "The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional."
+ },
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of events returned on one result page. By default the value is 250 events. The page size can never be larger than 2500 events. Optional.",
+ "minimum": 1,
+ "maximum": 2500
+ },
+ "originalStart": {
+ "type": "string",
+ "description": "The original start time of the instance in the result. Optional."
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Token specifying which result page to return. Optional."
+ },
+ "showDeleted": {
+ "type": "boolean",
+ "description": "Whether to include deleted events (with status equals 'cancelled') in the result. Cancelled instances of recurring events will still be included if singleEvents is False. Optional."
+ },
+ "timeMin": {
+ "type": "string",
+ "description": "Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset."
+ },
+ "timeMax": {
+ "type": "string",
+ "description": "Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset."
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Time zone used in the response. Optional. The default is the time zone of the calendar."
+ }
+ },
+ "required": [
+ "calendarId",
+ "eventId"
+ ]
+ }
+ },
+ {
+ "name": "watch_events",
+ "description": "Set up a webhook to receive notifications when events change.\n \n Sets up webhook notifications for event changes following Google Calendar API v3 structure.\n Returns a channel for managing the watch. Monitors events in the specified calendar for changes.\n \n Request Body Requirements:\n - calendarId: Required. Calendar identifier to watch for changes\n\n Optional Query Parameters:\n - eventTypes(string): Acceptable values are:\n \"birthday\": Special all-day events with an annual recurrence.\n \"default\": Regular events.\n \"focusTime\": Focus time events.\n \"fromGmail\": Events from Gmail.\n \"outOfOffice\": Out of office events.\n \"workingLocation\": Working location events. \n \n Request Body Requirements:\n - id: Required. Unique channel identifier\n - address: Required. Webhook URL to receive notifications\n - type: Optional. Channel type (default: \"web_hook\")\n - token: Optional. Optional token for webhook authentication\n - params: Optional. Additional channel parameters\n \n Webhook Notifications:\n - Server will send POST requests to the specified address\n - Notifications triggered by event changes:\n * Event created, updated, or deleted\n * Event moved between calendars\n * Event status changes\n \n Channel Management:\n - Each watch creates a unique notification channel\n - Channels can expire (set expiration time)\n - Multiple channels can watch the same calendar\n - Use unique channel IDs to avoid conflicts\n \n Response Structure:\n - Returns Channel resource with Google Calendar API v3 format:\n * kind: \"api#channel\"\n * id: Channel identifier\n * resourceId: Resource being watched\n * resourceUri: Resource URI path\n \n Status Codes:\n - 200: Success - Watch channel created successfully\n - 400: Bad Request - Invalid channel configuration\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "description": "Calendar identifier to watch for changes"
+ },
+ "id": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "type": {
+ "type": "string",
+ "description": "Channel type (web_hook)"
+ },
+ "address": {
+ "type": "string",
+ "description": "Webhook URL to receive notifications"
+ },
+ "token": {
+ "type": "string",
+ "description": "Optional token for webhook authentication"
+ },
+ "params": {
+ "type": "object",
+ "description": "Additional channel parameters",
+ "properties": {
+ "ttl": {
+ "type": "string",
+ "description": "Time to live in seconds (string)."
+ }
+ }
+ },
+ "eventTypes": {
+ "type": "string",
+ "description": "Event types of resources to watch. Optional. This parameter can be repeated multiple times to watch resources of different types. If unset, returns all event types. Acceptable values are: 'birthday' - Special all-day events with an annual recurrence, 'default' - Regular events, 'focusTime' - Focus time events, 'fromGmail' - Events from Gmail, 'outOfOffice' - Out of office events, 'workingLocation' - Working location events."
+ }
+ },
+ "required": [
+ "calendarId",
+ "id",
+ "type",
+ "address"
+ ]
+ }
+ },
+ {
+ "name": "get_colors",
+ "description": "Retrieve the color definitions for calendars and events.\n \n Returns the global palette of color definitions used by Google Calendar.\n This endpoint provides static color data and does not require authentication \n or user context as it returns predefined color schemes.\n \n Color Structure:\n - calendar: Object mapping color IDs to calendar color definitions\n - event: Object mapping color IDs to event color definitions\n \n Each color definition contains:\n - background: The background color (hex format)\n - foreground: The foreground color for text (hex format)\n \n Available Calendar Colors: 24 predefined colors (IDs 1-24)\n Available Event Colors: 11 predefined colors (IDs 1-11)\n \n Usage Examples:\n - Get all available colors for UI color pickers\n - Validate color IDs before setting calendar/event colors\n - Display color options to users\n \n Response Structure:\n - Returns colors with Google Calendar API v3 format:\n * kind: \"calendar#colors\"\n * updated: Last modification timestamp\n * calendar: Object with calendar color definitions\n * event: Object with event color definitions\n \n Color Examples:\n - Calendar Color 1: Background \"#ac725e\" (brown), Foreground \"#1d1d1d\" (dark)\n - Event Color 1: Background \"#a4bdfc\" (light blue), Foreground \"#1d1d1d\" (dark)\n - Event Color 11: Background \"#dc2127\" (red), Foreground \"#1d1d1d\" (dark)\n \n API Endpoint: GET /colors\n \n Status Codes:\n - 200: Success - Color definitions retrieved\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {},
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_user_by_email",
+ "description": "Get user details by email address\n\nThis tool retrieves complete user information using their email address, including user ID, name, and other profile details.\n\n**API Endpoint:** GET /users/email/{email}\n\n**Parameters:**\n- email (required): The email address to lookup\n\n**Returns:**\nComplete user information including id, name, given_name, family_name, picture, locale, timezone, is_active, is_verified, etc.\n\n**Example:**\n```json\n{\n \"email\": \"user@example.com\"\n}\n```",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Email address to lookup"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ }
+ },
+ {
+ "name": "get_settings",
+ "description": "Retrieve a specific user setting by ID.\n\n Returns the value of a setting resource by its ID.\n Follows Google Calendar API v3 `/settings/{settingId}` structure.\n\n Request Body Requirements:\n - settingId: Required. Unique identifier of the setting (e.g., \"timezone\")\n\n Response Structure:\n - kind: \"calendar#setting\"\n - etag: ETag of the setting\n - id: Unique setting identifier\n - value: Current value of the setting\n - user_id: ID of the user who owns the setting\n\n Status Codes:\n - 200: Success - Setting returned successfully\n - 404: Not Found - No setting exists with the given ID\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "settingId": {
+ "type": "string",
+ "description": "Unique identifier of the setting (e.g., 'timezone')",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "settingId"
+ ]
+ }
+ },
+ {
+ "name": "list_settings",
+ "description": "List all visible user settings.\n\n Retrieves all settings that are visible to the authenticated user.\n Follows the structure of Google Calendar API v3 `/settings` endpoint.\n\n No request body required.\n\n Response Structure:\n - kind: \"calendar#settings\"\n - etag: ETag for the entire settings collection\n - items: Array of setting resources, each containing:\n * kind: \"calendar#setting\"\n * etag: ETag of the setting\n * id: Unique identifier of the setting (e.g., \"timezone\")\n * value: Current value of the setting\n\n Status Codes:\n - 200: Success - List of settings returned\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {},
+ "required": []
+ }
+ },
+ {
+ "name": "watch_settings",
+ "description": "Watch for changes to user settings.\n\n Sets up a notification channel to receive updates when settings change.\n Follows Google Calendar API v3 `/settings/watch` structure.\n\n Creates a watch channel that will send webhook notifications to the specified\n address whenever settings are modified. The channel will automatically expire\n after a maximum of 24 hours or at the specified expiration time.\n\n Request Body Requirements:\n - id: Required. Unique identifier for the channel\n - type: Optional. Channel type (defaults to \"web_hook\")\n - address: Required. URL where notifications will be sent\n - token: Optional. Verification token for webhook security\n - params: Optional. Additional parameters as key-value pairs\n\n Optional Parameters:\n - token: Optional token for webhook authentication\n - params: Additional channel parameters\n\n Response Structure:\n - kind: \"api#channel\"\n - id: Channel identifier\n - resourceId: Resource being watched\n - resourceUri: URI of the resource (\"/settings\")\n - token: Verification token (if provided)\n - expiration: Channel expiration time\n\n Webhook Notification Format:\n Your webhook will receive POST requests with this payload:\n {\n \"kind\": \"api#channel\",\n \"id\": \"channel-id\",\n \"resourceId\": \"settings-user-id\",\n \"resourceUri\": \"/settings\",\n \"eventType\": \"update|insert|delete\",\n \"resourceState\": \"sync\",\n \"timestamp\": \"2024-10-01T18:30:00Z\",\n \"data\": {\n \"kind\": \"calendar#setting\",\n \"id\": \"setting-id\",\n \"value\": \"new-value\",\n \"oldValue\": \"previous-value\",\n \"user_id\": \"user-id\"\n }\n }\n\n Status Codes:\n - 200: Success - Watch channel created\n - 400: Bad Request - Invalid request parameters\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique identifier for the watch channel",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of notification channel",
+ "default": "web_hook",
+ "enum": [
+ "web_hook"
+ ]
+ },
+ "address": {
+ "type": "string",
+ "description": "URL where webhook notifications will be sent",
+ "format": "uri",
+ "minLength": 1
+ },
+ "token": {
+ "type": "string",
+ "description": "Optional verification token for webhook security"
+ },
+ "params": {
+ "type": "object",
+ "description": "Additional parameters as key-value pairs",
+ "properties": {
+ "ttl": {
+ "type": "string",
+ "description": "Time to live in seconds (string)."
+ }
+ }
+ }
+ },
+ "required": [
+ "id",
+ "type",
+ "address"
+ ]
+ }
+ },
+ {
+ "name": "get_acl_rule",
+ "description": "Retrieve an access control rule by ID.\n\n Fetches the ACL rule for a calendar by rule ID.\n Follows the structure of Google Calendar API v3 `/calendars/{calendarId}/acl/{ruleId}`.\n\n Required Parameters:\n - calendarId: Calendar identifier\n - ruleId: ACL rule identifier\n\n Response Structure:\n - kind: \"calendar#aclRule\"\n - etag: ETag\n - id: ACL rule ID\n - scope: { type, value }\n - role: ACL role (e.g., \"reader\", \"writer\")\n\n Status Codes:\n - 200: Success\n - 404: Not Found\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "ruleId": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId",
+ "ruleId"
+ ]
+ }
+ },
+ {
+ "name": "list_acl_rules",
+ "description": "List ACL rules for a calendar with pagination and filtering support.\n\n Returns access control rules for the given calendar with support for pagination and incremental synchronization.\n Follows the structure of Google Calendar API v3 `/calendars/{calendarId}/acl`.\n\n Required Parameters:\n - calendarId: Calendar identifier\n\n Optional Parameters:\n - maxResults: Maximum number of entries returned on one result page (1-250, default 100)\n - pageToken: Token specifying which result page to return\n - showDeleted: Whether to include deleted ACLs (role=\"none\") in the result (default False)\n - syncToken: Token for incremental synchronization, returns only entries changed since token\n\n Response Structure:\n - kind: \"calendar#acl\"\n - etag: ETag of the ACL collection\n - items: Array of ACL rules\n - nextPageToken: Token for next page (if more results available)\n - nextSyncToken: Token for next sync operation\n\n Synchronization:\n - When syncToken is provided, showDeleted is automatically set to True\n - Deleted ACLs are always included in sync responses\n - If syncToken expires, server responds with 410 GONE\n\n Status Codes:\n - 200: Success\n - 400: Bad Request (invalid parameters)\n - 410: Gone (sync token expired)\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "maxResults": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 250,
+ "default": 100,
+ "description": "Maximum number of entries returned on one result page"
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Token specifying which result page to return"
+ },
+ "showDeleted": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to include deleted ACLs in the result"
+ },
+ "syncToken": {
+ "type": "string",
+ "description": "Token for incremental synchronization"
+ }
+ },
+ "required": [
+ "calendarId"
+ ]
+ }
+ },
+ {
+ "name": "insert_acl_rule",
+ "description": "Insert a new access control rule.\n\n Adds a new ACL rule to the specified calendar.\n Equivalent to: POST /calendars/{calendarId}/acl\n\n Required Parameters:\n - calendarId: Calendar identifier\n - rule: ACL rule input (scope, role)\n\n Optional Parameters:\n - sendNotifications: Whether to send notifications about the calendar sharing change (default: True)\n\n Response Structure:\n - kind: \"calendar#aclRule\"\n - etag: ETag\n - id: ACL rule ID\n - scope: { type, value }\n - role: ACL role\n\n Status Codes:\n - 201: Created\n - 400: Bad Request\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "scope": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sendNotifications": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to send notifications about the calendar sharing change"
+ }
+ },
+ "required": [
+ "calendarId",
+ "scope",
+ "role"
+ ]
+ }
+ },
+ {
+ "name": "update_acl_rule",
+ "description": "Fully update an existing ACL rule.\n\n Replaces an ACL rule with a new one.\n Equivalent to: PUT /calendars/{calendarId}/acl/{ruleId}\n\n Required Parameters:\n - calendarId: Calendar identifier\n - ruleId: ACL rule ID\n - rule: Complete rule replacement (scope, role)\n\n Optional Parameters:\n - sendNotifications: Whether to send notifications about the calendar sharing change (default: True)\n\n Response:\n - Updated ACL rule object\n\n Status Codes:\n - 200: Success\n - 404: Not Found\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "ruleId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "scope": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sendNotifications": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to send notifications about the calendar sharing change"
+ }
+ },
+ "required": [
+ "calendarId",
+ "ruleId",
+ "scope"
+ ]
+ }
+ },
+ {
+ "name": "patch_acl_rule",
+ "description": "Partially update an ACL rule.\n\n Allows modifying select fields of an ACL rule.\n Equivalent to: PATCH /calendars/{calendarId}/acl/{ruleId}\n\n Required Parameters:\n - calendarId: Calendar identifier\n - ruleId: ACL rule ID\n - rule: Partial updates (any of: scope, role)\n\n Optional Parameters:\n - sendNotifications: Whether to send notifications about the calendar sharing change (default: True)\n\n Response:\n - Updated ACL rule object\n\n Status Codes:\n - 200: Success\n - 404: Not Found\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "ruleId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "scope": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "role": {
+ "type": "string"
+ },
+ "sendNotifications": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to send notifications about the calendar sharing change"
+ }
+ },
+ "required": [
+ "calendarId",
+ "ruleId"
+ ]
+ }
+ },
+ {
+ "name": "delete_acl_rule",
+ "description": "Delete an ACL rule.\n\n Deletes a specific ACL rule from the calendar.\n Equivalent to: DELETE /calendars/{calendarId}/acl/{ruleId}\n\n Required Parameters:\n - calendarId: Calendar identifier\n - ruleId: ACL rule ID\n\n Response:\n - No content (204) on success\n\n Status Codes:\n - 204: No Content\n - 404: Not Found\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "ruleId": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "calendarId",
+ "ruleId"
+ ]
+ }
+ },
+ {
+ "name": "watch_acl",
+ "description": "Set up a webhook to receive notifications when ACL rules change.\n\n Sets up webhook notifications for ACL rule changes following Google Calendar API v3 structure.\n Returns a channel for managing the watch. Monitors ACL rules in the specified calendar for changes.\n\n Equivalent to: POST /calendars/{calendarId}/acl/watch\n\n Required Parameters:\n - calendarId: Calendar identifier to watch for ACL changes\n - id: Unique channel identifier\n - address: Webhook URL to receive notifications\n - type: Channel type (default: \"web_hook\")\n \n\n Optional Parameters:\n - token: Optional token for webhook authentication\n - params: Additional channel parameters\n\n Response Structure:\n - Returns Channel resource with Google Calendar API v3 format:\n * kind: \"api#channel\"\n * id: Channel identifier\n * resourceId: Resource being watched\n * resourceUri: Resource URI path\n * token: Authentication token (if provided)\n * expiration: Channel expiration time (if set)\n\n Channel Management:\n - Each watch creates a unique notification channel\n - Channels can expire (set expiration time)\n - Multiple channels can watch the same calendar ACL\n - Use unique channel IDs to avoid conflicts\n\n Status Codes:\n - 200: Success - Watch channel created successfully\n - 400: Bad Request - Invalid channel configuration\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "calendarId": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Calendar identifier to watch for ACL changes"
+ },
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Unique channel identifier"
+ },
+ "type": {
+ "type": "string",
+ "default": "web_hook",
+ "description": "Channel type (only 'web_hook' supported)"
+ },
+ "address": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Webhook URL to receive notifications"
+ },
+ "token": {
+ "type": "string",
+ "description": "Optional token for webhook authentication"
+ },
+ "params": {
+ "type": "object",
+ "description": "Additional channel parameters",
+ "properties": {
+ "ttl": {
+ "type": "string",
+ "description": "Time to live in seconds (string)."
+ }
+ }
+ }
+ },
+ "required": [
+ "calendarId",
+ "id",
+ "type",
+ "address"
+ ]
+ }
+ },
+ {
+ "name": "query_freebusy",
+ "description": "Query free/busy information for a set of calendars.\n \n Returns free/busy information for specified calendars following Google Calendar API v3 structure.\n Shows busy time periods when calendars have confirmed events that block time.\n Essential for scheduling meetings and finding available time slots.\n \n Request Body Requirements:\n - timeMin: Required. Lower bound for the query (RFC3339 timestamp)\n - timeMax: Required. Upper bound for the query (RFC3339 timestamp)\n - items: Required. List of calendar identifiers to query\n \n Optional Parameters:\n - timeZone: Time zone for the query (default: UTC)\n - groupExpansionMax: Maximum number of calendars to expand for groups\n - calendarExpansionMax: Maximum number of events to expand for calendars\n \n Time Period Handling:\n - Only confirmed events block time (status = \"confirmed\")\n - Transparent events do not block time\n - Overlapping events are merged into continuous busy periods\n - Results are clipped to the requested time range\n \n Response Structure:\n - Returns FreeBusy resource with Google Calendar API v3 format:\n * kind: \"calendar#freeBusy\"\n * timeMin: Query start time\n * timeMax: Query end time\n * calendars: Object with calendar IDs as keys\n * Each calendar contains:\n - busy: Array of busy time periods\n - errors: Array of errors (if any)\n \n Status Codes:\n - 200: Success - FreeBusy information retrieved successfully\n - 400: Bad Request - Invalid query parameters\n - 404: Not Found - Calendar not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "timeMin": {
+ "type": "string",
+ "description": "Lower bound for the query (RFC3339 timestamp)"
+ },
+ "timeMax": {
+ "type": "string",
+ "description": "Upper bound for the query (RFC3339 timestamp)"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Time zone for the query (IANA timezone, default: UTC)"
+ },
+ "groupExpansionMax": {
+ "type": "integer",
+ "description": "Maximum number of calendars to expand for groups"
+ },
+ "calendarExpansionMax": {
+ "type": "integer",
+ "description": "Maximum number of events to expand for calendars"
+ },
+ "items": {
+ "type": "array",
+ "description": "List of calendar identifiers to query",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Calendar identifier"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ }
+ },
+ "required": [
+ "timeMin",
+ "timeMax",
+ "items"
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/csm.json b/resources_servers/enterpriseops_gym/data/tools/csm.json
new file mode 100644
index 0000000000..80831712c5
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/csm.json
@@ -0,0 +1,6936 @@
+{
+ "gym_name": "sn-csm-server",
+ "gym_url": "http://localhost:8001",
+ "snapshot_at": "2026-07-07T17:47:17.949442+00:00",
+ "tools": [
+ {
+ "name": "find_user",
+ "description": "Look up a user (portal customer, portal user or internal agent) by full name.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Full name of user, e.g., 'Harry Middleton'."
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "User's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name."
+ },
+ "email": {
+ "type": "string",
+ "description": "Unique email address of the user."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "User role assigned from the predefined list."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location associated with this record. This value references the primary key of the location in the location table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_user_by_email",
+ "description": "Look up a user (portal customer, portal user or internal agent) by email address.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Email address, e.g., 'harry.middleton@example.com'."
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "User's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name."
+ },
+ "email": {
+ "type": "string",
+ "description": "Email address of the user (unique)."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "User role assigned from the predefined list."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Foreign key referencing the user's location."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_account",
+ "description": "Retrieve an account by its exact name. Account is a company or organization that has a relationship with the business.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Exact account name, e.g., 'Wood and Sons'.",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Unique identifier of the account."
+ },
+ "name": {
+ "type": "string",
+ "description": "Exact name of the account (unique)."
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Type of the account."
+ },
+ "email_domain": {
+ "type": "string",
+ "description": "Email domain associated with the account, if any."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the account is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_contact_by_portal_user",
+ "description": "Find the contact record using the portal user associated with it. Portal user is a type of user that represents a customer accessing the support portal. Portal user is a user with role 'customer' in the user table.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ }
+ },
+ "required": [
+ "portal_user_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account associated with this contact."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the contact record is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_product",
+ "description": "Look up a product by its exact name. Product represents an item or service offered by the company.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Product name, e.g., 'Pulse Edge'.",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Exact name of the product (unique)."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Category of the product."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_product_by_id",
+ "description": "Retrieve a product by product ID. Product represents an item or service offered by the company. Each Product has a unique identifier called product_id.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": " Unique identifier of the product."
+ }
+ },
+ "required": [
+ "product_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Exact name of the product (unique)."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Category of the product."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_installed_product_by_serial",
+ "description": "Retrieve an installed product by its serial number. Installed Product represents a specific instance of a product that has been installed for a customer. The serial number is a unique identifier assigned to each installed product.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "serial_number": {
+ "type": "string",
+ "description": "Exact serial number of product.",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "serial_number"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the installed product."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account to which this installed product belongs."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product associated with this installation."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Location of the installed product, if specified."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Exact serial number of the installed product."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Lifecycle status of the installed product."
+ },
+ "warranty_end": {
+ "type": "string",
+ "format": "date",
+ "description": "Warranty expiration date of the installed product, if available."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_location",
+ "description": "Look up a location (site/campus) by exact given name for it. Location represents a physical site or campus or user's location where services or products are installed or the user resides.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Given Location name",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location."
+ },
+ "name": {
+ "type": "string",
+ "description": "Exact name of the location."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "City in which the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Country where the location resides."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the location is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_user_group",
+ "description": "Retrieve a user group by exact name. User Group represents a collection of users grouped together for assignment or organizational purposes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Exact name of the user group (unique).",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user group."
+ },
+ "name": {
+ "type": "string",
+ "description": "Exact name of the user group (unique)."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Type/category of the user group."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user group is active."
+ }
+ }
+ }
+ },
+ {
+ "name": "check_user_membership",
+ "description": "Verify that a user is a member of a specific user group. User Group represents a collection of users grouped together for assignment or organizational purposes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "User's unique id to check"
+ },
+ "group_id": {
+ "type": "integer",
+ "description": "User group's unique id to check"
+ }
+ },
+ "required": [
+ "user_id",
+ "group_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "exists": {
+ "type": "boolean",
+ "description": "Indicates whether the user is a member of the specified group."
+ },
+ "member_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "The member_id of the membership record if it exists, otherwise null."
+ }
+ }
+ }
+ },
+ {
+ "name": "assign_case_to_user",
+ "description": "Assign an existing case to a specific user (agent). Case represents a support ticket or issue that needs to be resolved. The assigned user takes care of the lifecycle of the case to its closure.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case to be assigned."
+ },
+ "assigned_to_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user (agent) to assign the case to. It is a user who is assigned to handle the case. The user has record in the user table with at least role 'agent'."
+ }
+ },
+ "required": [
+ "case_id",
+ "assigned_to_user_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_status": {
+ "type": "string",
+ "description": "Result of the assignment operation."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "The user_id of the agent the case was assigned to. It is a user who is assigned to handle the case. The user has record in the user table with at least role 'agent'."
+ },
+ "assigned_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case assignment was updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "set_case_assignment_group",
+ "description": "Set or change the assignment group for a case. Setting the assignment group helps route the case to the appropriate team for handling.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case to update."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the assignment group to set."
+ }
+ },
+ "required": [
+ "case_id",
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "description": "Result of the update operation."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "The ID of the assignment group that the case was set to."
+ },
+ "set_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the assignment group update occurred."
+ }
+ }
+ }
+ },
+ {
+ "name": "list_users",
+ "description": "List users with optional filters. None of the filters are mandatory. If no filters are provided, all users will be returned.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Filter by user email address (exact match) (unique)."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "Filter by unique user identifier."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "Filter by user's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "Filter by user's last name."
+ },
+ "phone": {
+ "type": "string",
+ "description": "Filter by phone number."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "Filter by user role (admin, agent, manager, or customer)."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Filter by location identifier."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (true = active, false = inactive)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return only users created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return only users created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "User's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name."
+ },
+ "email": {
+ "type": "string",
+ "description": "Email address of the user (unique)."
+ },
+ "phone": {
+ "type": "string",
+ "description": "Phone number of the user, if provided."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "Role assigned to the user."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Identifier of the user's location."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the user record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "list_user_groups",
+ "description": "List user groups with optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Filter by unique group identifier."
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by group name (exact match, unique)."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (true = active, false = inactive)."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Filter by group type (support, backoffice, field, vendor)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return only groups created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return only groups created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user group."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the user group."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Type/category of the user group."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user group is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the group was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "list_group_members",
+ "description": "List user group members with optional filters. Combination of group_id and user_id is unique.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "member_id": {
+ "type": "integer",
+ "description": "Filter by unique membership identifier."
+ },
+ "group_id": {
+ "type": "integer",
+ "description": "Filter by group identifier."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "Filter by user identifier."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return only memberships created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return only memberships created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "member_id": {
+ "type": "integer",
+ "description": "Unique identifier of the group membership record."
+ },
+ "group_id": {
+ "type": "integer",
+ "description": "ID of the user group this membership belongs to."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "ID of the user who is a member of the group."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the membership record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "get_accounts",
+ "description": "List accounts with optional filters. All the inputs are optional, not providing any filter will return all accounts. Account represents a business entity or organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by unique account identifier."
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by account name (e.g., 'Acme Systems') (unique). Name of the company/organization associated with the account.",
+ "minLength": 1
+ },
+ "email_domain": {
+ "type": "string",
+ "description": "Filter by account email domain (e.g., 'acme.com'). it is the domain part of email addresses associated with the account or the website.",
+ "minLength": 1
+ },
+ "account_types": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ]
+ },
+ "description": "Filter by one or more account types (customer, partner, internal)."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (true = active, false = inactive)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return only accounts created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return only accounts created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Unique identifier of the account."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the account. It represents the company or organization associated with the account."
+ },
+ "email_domain": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Email domain associated with the account, if provided. It is the domain part of email addresses linked to the account or the company's website."
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Type of the account."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the account was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_contacts",
+ "description": "Find contacts with optional filters.All the inputs are optional, not providing any filter will return all accounts. Contact represents an individual associated with an account or a point of contact.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account this contact belongs to."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the contact is currently active."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "True if this is the primary contact for the account."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter for contacts created after this timestamp (ISO format)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter for contacts created before this timestamp (ISO format)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Identifier of the account this contact belongs to."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the contact is active."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "True if this contact is the primary contact for its account."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contact record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_locations",
+ "description": "Find locations with optional filters. All the inputs are optional, not providing any filter will return all locations. Location represents a physical site or campus or user's location where services or products are installed or the user resides.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the location."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the location is currently active."
+ },
+ "plot_no": {
+ "type": "string",
+ "description": "Plot number of the location."
+ },
+ "street": {
+ "type": "string",
+ "description": "Street address of the location."
+ },
+ "city": {
+ "type": "string",
+ "description": "City where the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "description": "Country where the location is situated."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter for locations created before this timestamp (ISO format)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter for locations created after this timestamp (ISO format)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the location."
+ },
+ "plot_no": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Plot number of the location, if available."
+ },
+ "street": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Street address of the location, if available."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "City where the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Country where the location is situated."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the location is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the location was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_products",
+ "description": "Find products with optional filters. All the inputs are optional, not providing any filter will return all products.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the product.",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Category of the product."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ },
+ "product_price": {
+ "type": "integer",
+ "description": "Price of the product."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter for products created before this timestamp (ISO format)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter for products created after this timestamp (ISO format)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the product."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Category of the product."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ },
+ "product_price": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Price of the product, if defined."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the product was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "installed_product_warranties_ended_count",
+ "description": "Count installed products whose warranty ended on or before the date provided, optionally filtered.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by owning account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by product ID."
+ },
+ "on_date": {
+ "type": "string",
+ "description": "Date (YYYY-MM-DD). Count warranties that ended on or before this date."
+ }
+ },
+ "required": [
+ "on_date"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "ended_count": {
+ "type": "integer",
+ "description": "Number of installed products whose warranty ended on or before the specified on_date, after applying any provided filters."
+ }
+ }
+ }
+ },
+ {
+ "name": "avg_installed_per_account_by_status",
+ "description": "Average installed products per account for each status (optionally filter by product/location).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by product ID."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Filter by location/site ID."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID for which the installed product count was calculated."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Installed product status category for the aggregated result."
+ },
+ "avg_installed_per_account": {
+ "type": "number",
+ "description": "Average number of installed products per account for this status category."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_installed_product_by_status",
+ "description": "Count installed products grouped by status with optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by owning account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by product ID."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Filter by location/site ID."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Installed product status category."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of installed products for this status category."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "retrieve_installed_products",
+ "description": "Retrieve installed products with rich filters. All filters are optional. If no filters are provided, all installed products will be returned. Installed products are items that have been deployed or set up for use at specific locations or accounts.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique installed product ID."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Filter by location/site ID. Unique identifier which relates to the location table record."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID. Unique identifier which relates to the account table record. An account represents a business entity or organization."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by product ID. Unique identifier which relates to the product table record."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Exact serial number of the installed product. Unique identifier assigned to the product by the manufacturer."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Current status of the installed product."
+ },
+ "warranty_end": {
+ "type": "string",
+ "description": "Exact warranty end date (YYYY-MM-DD)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return products created before this date (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return products created after this date (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Installed product record. An installed product is an item that has been deployed or set up for use at a specific location or account.",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique installed product ID."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Associated account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Associated product ID."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Associated location/site ID. Unique identifier which relates to the location table record."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Serial number of the installed product. Unique identifier assigned to the product by the manufacturer."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Current status of the installed product."
+ },
+ "warranty_end": {
+ "type": "string",
+ "description": "Warranty end date (YYYY-MM-DD)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Record creation timestamp."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_contract_by_status",
+ "description": "Count contracts grouped by status; optional filters. All inputs are optional; not providing any filter will return counts for all contracts. A contract represents a formal agreement between two or more parties.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter contracts by the owning account\u2019s unique ID. An account represents a business entity or organization."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Filter by type of contract (support, warranty, or subscription)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Contract status category."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of contracts for this status category."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "avg_contracts_per_account_by_status",
+ "description": "Average number of contracts per account for each status. Optionally filter by contract type.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Optional filter to calculate averages only for a specific contract type."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Contract status category."
+ },
+ "avg_contracts_per_account": {
+ "type": "number",
+ "description": "Average number of contracts per account for this status."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_contracts",
+ "description": "Find contracts with multiple filters including price range. All inputs are optional; not providing any filter will return all contracts. A contract represents a formal agreement between two or more parties.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contract."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Filter contracts by their current status."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter contracts by the owning account\u2019s ID. An account represents a business entity or organization."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Filter by contract type."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Contract start date (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "Contract end date (YYYY-MM-DD)."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Exact price of the contract in system currency."
+ },
+ "contract_price_range_start": {
+ "type": "integer",
+ "description": "Lower bound of contract price range filter."
+ },
+ "contract_price_range_end": {
+ "type": "integer",
+ "description": "Upper bound of contract price range filter."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Find contracts created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Find contracts created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contract."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Identifier of the owning account. An account represents a business entity or organization."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Type of contract."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Current contract status."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Contract price in system currency."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Contract start date (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "Contract end date (YYYY-MM-DD)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contract was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "total_sum_of_max_cases_per_support_level",
+ "description": "Sum max_cases_per_month from entitlements (optionally for one support_level).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level to filter entitlements. Options: standard, premium, enterprise."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "support_level": {
+ "type": "string",
+ "description": "Support level used for the aggregation (or 'all' if no filter was applied)."
+ },
+ "sum": {
+ "type": "integer",
+ "description": "Total sum of max_cases_per_month for the selected support level."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_entitlements",
+ "description": "Find entitlements with filters. All inputs are optional; not providing any filter will return all entitlements. An entitlement represents a customer's right to receive specific services or support based on their agreement.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {
+ "type": "integer",
+ "description": "Unique identifier of the entitlement."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter entitlements by associated account ID. An account represents a business entity or organization."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter entitlements by product ID. Unique identifier which relates to the product table record."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Filter entitlements by contract ID. Unique identifier which relates to the contract table record."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level associated with the entitlement."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Coverage hours offered under the entitlement (8x5, 12x6, 24x7)."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Maximum number of support cases allowed per month under this entitlement."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by entitlement status (true = active, false = inactive)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return entitlements created before this date (YYYY-MM-DD format)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return entitlements created after this date (YYYY-MM-DD format)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {
+ "type": "integer",
+ "description": "Unique identifier of the entitlement."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with this entitlement. An account represents a business entity or organization."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID linked to this entitlement (null means all products)."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Contract ID linked to this entitlement."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level assigned to this entitlement."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Coverage hours provided under this entitlement."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Maximum number of support cases allowed per month."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the entitlement is active (true) or inactive (false)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the entitlement was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "total_sum_of_target_mins_per_priority",
+ "description": "Sum target_mins over SLA definitions (optionally for one priority).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Optional filter: restrict the sum to SLA definitions that apply to this priority level."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "string",
+ "description": "Priority level used for the sum calculation, or 'all' if no priority filter was applied."
+ },
+ "sum": {
+ "type": "integer",
+ "description": "Total sum of target_mins for the selected priority level."
+ }
+ }
+ }
+ },
+ {
+ "name": "find_sla_definitions",
+ "description": "Find SLA definitions with filters. All inputs are optional; not providing any filter will return all SLA definitions. An SLA definition outlines the expected service levels for response and resolution times based on case priority.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Unique identifier of the SLA definition."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition (e.g., 'SLA Response - Critical').",
+ "minLength": 1
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "SLA metric type. 'response' = first response SLA, 'resolution' = issue resolution SLA."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target duration for the SLA in minutes."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether the SLA timer pauses when the case is in a pending state."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level this SLA definition applies to."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the SLA definition is active (true) or inactive (false)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return SLA definitions created before this date (YYYY-MM-DD format)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return SLA definitions created after this date (YYYY-MM-DD format)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Unique identifier of the SLA definition."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition."
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "SLA metric type ('response' or 'resolution')."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target duration for the SLA in minutes."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether the SLA pauses when the case is pending."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority that this SLA definition applies to."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether this SLA definition is active (true) or inactive (false)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA definition was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "average_target_mins_per_priority",
+ "description": "Average target_mins grouped by applies_to_priority; optionally limit to a priority list.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority_list": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ]
+ },
+ "description": "Optional list of priorities. If provided, averages are calculated only for these priority levels."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level for which the average target minutes were calculated."
+ },
+ "avg_target_mins": {
+ "type": "number",
+ "description": "Average target_mins value for this priority."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "get_cases_assigned_to",
+ "description": "List cases filtered by assignment_group_id and/or assigned_to.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Filter by the assignment group responsible for the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "Filter by the specific user ID the case is assigned to."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "number": {
+ "type": "string",
+ "description": "System-generated unique case number."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with the case."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact ID who raised the case."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID related to the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Installed product ID associated with the case."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was raised."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Current state of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description summarizing the case issue."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID responsible for the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "User ID assigned to the case."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "get_average_case_reopen_count",
+ "description": "Average of reopen_count on cases (optional filters).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was created."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Current state of the case."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "avg_reopen_count": {
+ "type": "number",
+ "description": "Average value of the reopen_count field for the selected cases."
+ }
+ }
+ }
+ },
+ {
+ "name": "get_count_of_cases_priority_wise",
+ "description": "Count cases per priority (or for one priority).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Optional filter to count cases only for this priority level."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level for which the case count is calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of cases for the specified priority."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_case_for_assignment_group",
+ "description": "Count cases for an assignment group with optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID to filter cases."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Optional filter by case state."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Optional filter by case priority."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Optional filter by channel."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter cases by account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter cases by product ID."
+ }
+ },
+ "required": [
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "The assignment group ID for which the case count was calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of cases matching the provided filters for the given assignment group."
+ }
+ }
+ }
+ },
+ {
+ "name": "count_case_by_state",
+ "description": "Count cases grouped by state with optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter cases by account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter cases by product ID."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Filter by assignment group ID."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "Filter by assigned user ID."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Filter by priority level."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Filter by channel."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "State of the case for which the count is calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of cases in this state that match the applied filters."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "avg_reopen_count_for_assignment_group",
+ "description": "Average reopen_count for cases in an assignment group (optional filters).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID to filter cases."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Optional filter by case state."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Optional filter by priority level."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Optional filter by channel."
+ }
+ },
+ "required": [
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "The assignment group ID for which the average reopen count was calculated."
+ },
+ "avg_reopen_count": {
+ "type": "number",
+ "description": "Average reopen_count value for cases matching the provided filters."
+ }
+ }
+ }
+ },
+ {
+ "name": "search_cases",
+ "description": "Search cases with rich filters and date bounds on sys_created_on. All inputs are optional; not providing any filter will return all cases. A case represents a customer-reported issue or request that requires tracking and resolution.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "number": {
+ "type": "string",
+ "description": "Case number (unique human-readable reference)."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID. An account represents a business entity or organization."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Filter by contact ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by product ID. Unique identifier which relates to the product table record."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Filter by installed product ID. Unique identifier which relates to the installed product table record."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was communicated/created."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "State of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description of the case."
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Reason for escalation."
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Filter by number of times the case was reopened."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Filter cases closed on a specific date (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return cases created before this date (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return cases created after this date (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "number": {
+ "type": "string",
+ "description": "Human-readable unique case number."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account associated with the case."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact who created the case."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product associated with the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Installed product linked to the case."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was created."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Current state of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description summarizing the case issue."
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Indicates whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Reason for escalation, if applicable."
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Number of times the case has been reopened."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case was last updated."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Date/time when the case was closed."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group responsible for handling the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "User assigned to work on the case."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_case_slas",
+ "description": "Find case_sla rows with flexible filters. All inputs are optional; not providing any filter will return all case_sla records. A case_sla record tracks the SLA status for a specific case based on the applied SLA definition.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_sla record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case linked to this SLA record."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "ID of the SLA definition applied to the case."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Current stage of the SLA tracking."
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Timestamp when SLA tracking started (YYYY-MM-DD HH:MM:SS)."
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA was breached (true/false)."
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Timestamp when SLA was completed, if applicable."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_sla record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case associated with this SLA record."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "ID of the SLA definition applied to the case."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Current stage of SLA tracking."
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Timestamp when SLA tracking started (YYYY-MM-DD HH:MM:SS)."
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Expected or actual SLA breach timestamp."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA has been breached (true/false)."
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Timestamp when SLA tracking was completed, if applicable."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_stage_wise_breached_case_sla_counts",
+ "description": "Stage-wise counts of breached case_sla rows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Stage to filter SLA breach counts."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "in_progress": {
+ "type": "integer",
+ "description": "Number of breached case_sla records in the 'in_progress' stage."
+ },
+ "paused": {
+ "type": "integer",
+ "description": "Number of breached case_sla records in the 'paused' stage."
+ },
+ "completed": {
+ "type": "integer",
+ "description": "Number of breached case_sla records in the 'completed' stage."
+ },
+ "canceled": {
+ "type": "integer",
+ "description": "Number of breached case_sla records in the 'canceled' stage."
+ }
+ },
+ "additionalProperties": {
+ "type": "integer",
+ "description": "Count of breached SLA records for a dynamically returned stage."
+ }
+ }
+ },
+ {
+ "name": "find_interactions",
+ "description": "Find interactions with rich time filters on started_at/ended_at and sys_created_on. All inputs are optional; not providing any filter will return all interactions. An interaction represents a communication event between a customer and support, such as a phone call, email, chat session, or social media message that is logged.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "interaction_id": {
+ "type": "integer",
+ "description": "Filter by unique interaction ID."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Filter by channel."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID. An account represents a business entity or organization."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Filter by contact ID. A contact is an individual associated with an account."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Filter by case ID. A case represents a customer-reported issue or request."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "Filter by user who interacted. This is the agent or user who handled the interaction."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Filter by status."
+ },
+ "started_at": {
+ "type": "string",
+ "description": "Exact match for interaction start time."
+ },
+ "ended_at": {
+ "type": "string",
+ "description": "Exact match for interaction end time."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Find interactions created before this timestamp."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Find interactions created after this timestamp."
+ },
+ "started_at_before": {
+ "type": "string",
+ "description": "Find interactions started before this timestamp."
+ },
+ "started_at_after": {
+ "type": "string",
+ "description": "Find interactions started after this timestamp."
+ },
+ "ended_at_before": {
+ "type": "string",
+ "description": "Find interactions ended before this timestamp."
+ },
+ "ended_at_after": {
+ "type": "string",
+ "description": "Find interactions ended after this timestamp."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "interaction_id": {
+ "type": "integer",
+ "description": "Unique identifier of the interaction."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel over which the interaction took place."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with the interaction, if any."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact ID associated with the interaction, if any."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID linked to this interaction, if applicable."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "User ID of the agent or user who handled the interaction."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Current status of the interaction."
+ },
+ "started_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction started."
+ },
+ "ended_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction ended, if available."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_interaction_by_status",
+ "description": "Count interactions grouped by status with optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Filter by contact ID."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Filter by case ID."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Filter by channel."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Interaction status for which the count is calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of interactions matching this status and the applied filters."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "avg_interactions_per_case_by_status",
+ "description": "Average interactions per case, grouped by interaction status; optional filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Filter by account ID."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Filter by contact ID."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Filter by channel."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Interaction status for which the average interactions per case is calculated."
+ },
+ "avg_interactions_per_case": {
+ "type": "number",
+ "description": "Average number of interactions per case for this status, based on matching records."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "get_channel_wise_case_count",
+ "description": "Count cases per channel; if channel provided returns only that channel's count.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Optional filter to count cases only for this channel."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "web": {
+ "type": "integer",
+ "description": "Count of cases created through the 'web' channel."
+ },
+ "email": {
+ "type": "integer",
+ "description": "Count of cases created through the 'email' channel."
+ },
+ "phone": {
+ "type": "integer",
+ "description": "Count of cases created through the 'phone' channel."
+ },
+ "chat": {
+ "type": "integer",
+ "description": "Count of cases created through the 'chat' channel."
+ },
+ "social": {
+ "type": "integer",
+ "description": "Count of cases created through the 'social' channel."
+ },
+ "alert": {
+ "type": "integer",
+ "description": "Count of cases created through the 'alert' channel."
+ },
+ "community": {
+ "type": "integer",
+ "description": "Count of cases created through the 'community' channel."
+ }
+ }
+ }
+ },
+ {
+ "name": "retrieve_knowledge",
+ "description": "Retrieve knowledge articles with full-text search on title/body and structured filters. All inputs are optional; not providing any filter will return all knowledge articles. A knowledge article is a documented piece of information that provides solutions, answers, or guidance on specific topics to help users resolve issues or learn about products and services.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "search_text": {
+ "type": "string",
+ "description": "Full-text search across article title and body. Free form search."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Filter by unique knowledge article ID."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Filter by knowledge base number."
+ },
+ "title": {
+ "type": "string",
+ "description": "Filter by article title."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Filter by article lifecycle state."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Filter by article visibility. Internal for staff, external for customers/public."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Filter by related product ID."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "Filter by user ID of the article owner. User who authored the article."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Retrieve articles created before this timestamp."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Retrieve articles created after this timestamp."
+ },
+ "limit": {
+ "type": "integer",
+ "description": "Limit the number of articles returned."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Knowledge base article number (system-generated unique reference, e.g., KB000001)."
+ },
+ "title": {
+ "type": "string",
+ "description": "Title of the knowledge article."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Lifecycle state of the article."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Visibility of the article: internal staff or external customers."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "ID of the related product associated with this article, if any."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "User ID of the article owner/author."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the knowledge article record was created."
+ },
+ "body": {
+ "type": "string",
+ "description": "Body/content of the knowledge article."
+ },
+ "score": {
+ "type": "number",
+ "description": "Relevance score for the article when full-text search is used. Higher values indicate better matches."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_case_knowledge_linkages",
+ "description": "Find case-knowledge linkages (case_knowledge). Combination of case id and knowledge id is unique. All inputs are optional; not providing any filter will return all case_knowledge linkages. A case_knowledge linkage represents the association between a specific case and a knowledge article, indicating how the article was utilized in relation to the case, such as being suggested, applied, or used as a resolution.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Filter by usage context: suggested, applied, or resolution."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case associated with the knowledge article."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "ID of the linked knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "How the knowledge article was used for the case (suggested, applied, or resolution)."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "find_notifications",
+ "description": "Find notifications with flexible filters. All inputs are optional; not providing any filter will return all notifications. A notification represents a message or alert sent to users or stakeholders to inform them about important updates, events, or actions related to cases, knowledge articles, or other system activities.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the notification."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID associated with this notification, if any."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID linked to this notification, if any."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address for the notification."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type of notification, e.g., report, update, alert, reminder, solution_proposal, next_steps, or other."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delivery status of the notification."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the notification was created."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the notification."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID associated with this notification."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID linked to this notification, if any."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address for the notification."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type of notification (report, update, alert, reminder, solution_proposal, next_steps, or other)."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delivery status of the notification."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the notification record was created."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_notifications_by_status",
+ "description": "Count notifications grouped by status; if status provided returns only that status.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Optional filter to count only notifications with this status."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Notification delivery status for which the count is calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of notifications with this status."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "count_notifications_by_case",
+ "description": "Count notifications for a given case; if case_id omitted, returns total count.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Optional case ID to filter notifications by case."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer",
+ "description": "Number of notifications matching the case filter (or total notifications if no case_id was provided)."
+ }
+ }
+ }
+ },
+ {
+ "name": "avg_notifications_by_case",
+ "description": "Average notifications per case; if case given, returns that case's count as a float.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case": {
+ "type": "integer",
+ "description": "Optional case ID; if provided, returns notification count for that case."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "avg_count": {
+ "type": "number",
+ "description": "Average number of notifications per case, or the notification count for a specific case when a case ID is provided."
+ }
+ }
+ }
+ },
+ {
+ "name": "count_notifications_by_type",
+ "description": "Count notifications grouped by type; optionally limit to a list of types.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ]
+ },
+ "description": "Optional list of notification types to filter counts."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Notification type for which the count is calculated."
+ },
+ "count": {
+ "type": "integer",
+ "description": "Number of notifications for this type."
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_user",
+ "description": "Create a new user record. A user represents an individual who interacts with the system, such as support agents, managers, or customers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "first_name": {
+ "type": "string",
+ "description": "User's first name.",
+ "minLength": 1
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name.",
+ "minLength": 1
+ },
+ "email": {
+ "type": "string",
+ "description": "Unique email address of the user.",
+ "minLength": 1
+ },
+ "phone": {
+ "type": "string",
+ "description": "Contact phone number of the user."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "User role within the system."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Associated location identifier. Optional. Location where user resides/works."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user is active (true) or inactive (false)."
+ }
+ },
+ "required": [
+ "first_name",
+ "last_name",
+ "email",
+ "role",
+ "active"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the newly created user."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "User's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name."
+ },
+ "email": {
+ "type": "string",
+ "description": "Unique email address of the user."
+ },
+ "phone": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Contact phone number of the user, if provided."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "User's role within the system."
+ },
+ "location_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Associated location identifier, if provided."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the user account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the user was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the user record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_user_details",
+ "description": "Update an existing user (partial updates supported). A user represents an individual who interacts with the system, such as support agents, managers, or customers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user to update."
+ },
+ "email": {
+ "type": "string",
+ "description": "New email address for the user.",
+ "minLength": 1
+ },
+ "first_name": {
+ "type": "string",
+ "description": "Updated first name of the user.",
+ "minLength": 1
+ },
+ "last_name": {
+ "type": "string",
+ "description": "Updated last name of the user.",
+ "minLength": 1
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Updated active status (true = active, false = inactive)."
+ },
+ "phone": {
+ "type": "string",
+ "description": "Updated phone number."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "Updated role of the user."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Updated location identifier."
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user."
+ },
+ "first_name": {
+ "type": "string",
+ "description": "User's first name."
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name."
+ },
+ "email": {
+ "type": "string",
+ "description": "Email address of the user (unique)."
+ },
+ "phone": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User's phone number, if provided."
+ },
+ "role": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "customer"
+ ],
+ "description": "Role assigned to the user."
+ },
+ "location_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Identifier of the user's location, if provided."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the user was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the user record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_user_group",
+ "description": "Create a user group. A user group is a collection of users who share similar roles, responsibilities, or access permissions within the system, allowing for efficient management and assignment of tasks or cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the user group.",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Type of the user group (support, backoffice, field, vendor)."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the group is active (true) or inactive (false)."
+ }
+ },
+ "required": [
+ "name",
+ "type",
+ "active"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user group."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the user group (unique)."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Type of the user group."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user group is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the group was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the group record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_user_group",
+ "description": "Update a user group (partial updates supported). A user group is a collection of users who share similar roles, responsibilities, or access permissions within the system, allowing for efficient management and assignment of tasks or cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the group to update."
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated name of the group.",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Updated type of the group."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Updated active status (true = active, false = inactive)."
+ }
+ },
+ "required": [
+ "group_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Unique identifier of the user group."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the user group (unique)."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "backoffice",
+ "field",
+ "vendor"
+ ],
+ "description": "Type of the user group."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the group is currently active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the group was originally created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the group was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_group_member",
+ "description": "Add a user to a group. Combination of group_id and user_id should be unique.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Identifier of the group the user will be added to."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "Identifier of the user being added to the group."
+ }
+ },
+ "required": [
+ "group_id",
+ "user_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "member_id": {
+ "type": "integer",
+ "description": "Unique identifier of the newly created group membership record."
+ },
+ "group_id": {
+ "type": "integer",
+ "description": "Identifier of the user group the user was added to."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "Identifier of the user who was added to the group."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the membership record was created."
+ }
+ }
+ }
+ },
+ {
+ "name": "remove_group_membership",
+ "description": "Remove a membership by member_id or by (group_id, user_id).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "member_id": {
+ "type": "integer",
+ "description": "Unique identifier of the membership to remove."
+ },
+ "group_id": {
+ "type": "integer",
+ "description": "Group identifier (used with user_id if member_id is not provided)."
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "User identifier (used with group_id if member_id is not provided)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "integer",
+ "description": "Number of membership records deleted (0 or 1)."
+ }
+ }
+ }
+ },
+ {
+ "name": "create_new_account",
+ "description": "Create/onboard an account. An account represents a company or organization that is a customer, partner, or internal entity within the system.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the account (e.g., 'Stark Industries')(unique).",
+ "minLength": 1
+ },
+ "email_domain": {
+ "type": "string",
+ "description": "Primary email domain associated with the account (e.g., 'stark-industries.com').",
+ "minLength": 1
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Type of account: customer, partner, or internal."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the account is active (true) or inactive (false)."
+ }
+ },
+ "required": [
+ "name",
+ "account_type",
+ "active"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Unique identifier of the newly created account."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the account (unique)."
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Type of the account."
+ },
+ "email_domain": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Primary email domain of the account, if provided."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the account was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the account record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_account_details",
+ "description": "Update an account (partial updates supported). An account represents a company or organization that is a customer, partner, or internal entity within the system.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Unique identifier of the account to update."
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated account name (unique).",
+ "minLength": 1
+ },
+ "email_domain": {
+ "type": "string",
+ "description": "Updated email domain for the account.",
+ "minLength": 1
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Updated active status (true = active, false = inactive)."
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Updated account type."
+ }
+ },
+ "required": [
+ "account_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Unique identifier of the account."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the account (unique)."
+ },
+ "account_type": {
+ "type": "string",
+ "enum": [
+ "customer",
+ "partner",
+ "internal"
+ ],
+ "description": "Type of the account."
+ },
+ "email_domain": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Email domain associated with the account, if provided."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the account is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the account was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the account was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "create_contact",
+ "description": "Create a new contact. A contact represents an individual associated with an account, such as a customer representative or point of contact for communication.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account the contact belongs to."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the contact is active upon creation."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "Set to true if this contact should be the account's primary contact."
+ }
+ },
+ "required": [
+ "account_id",
+ "portal_user_id",
+ "active",
+ "is_primary"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account this contact belongs to."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the contact is active."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "True if this is the primary contact for the account."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contact was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contact record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_contact",
+ "description": "Update a contact (partial updates supported). A contact represents an individual associated with an account, such as a customer representative or point of contact for communication.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact to update."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID to update for this contact."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Updated Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Update the active status of the contact."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "Update whether this is the primary contact."
+ }
+ },
+ "required": [
+ "contact_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "contact_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contact."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account this contact belongs to."
+ },
+ "portal_user_id": {
+ "type": "integer",
+ "description": "Unique identifier of the portal user associated with this record. This value references the primary key of the user in the User table."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the contact is active."
+ },
+ "is_primary": {
+ "type": "boolean",
+ "description": "True if this contact is the primary contact for the account."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contact was originally created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contact was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_location",
+ "description": "Create a new location (site). A location represents a physical site or office associated with the organization, such as branch offices, warehouses, or service centers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the location/site (e.g., 'Downtown HQ').",
+ "minLength": 1
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the location is active (true) or inactive (false)."
+ },
+ "plot_no": {
+ "type": "string",
+ "description": "Plot number of the location (optional)."
+ },
+ "street": {
+ "type": "string",
+ "description": "Street address of the location (optional)."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "City where the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Country where the location is situated."
+ }
+ },
+ "required": [
+ "name",
+ "active",
+ "city",
+ "country"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the location/site."
+ },
+ "plot_no": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Plot number of the location, if provided."
+ },
+ "street": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Street address of the location, if provided."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "City in which the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Country in which the location is situated."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the location is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the location record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the location record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_location",
+ "description": "Update an existing location (partial updates allowed). A location represents a physical site or office associated with the organization, such as branch offices, warehouses, or service centers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location to update."
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated name of the location/site.",
+ "minLength": 1
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Updated active status (true = active, false = inactive)."
+ },
+ "plot_no": {
+ "type": "string",
+ "description": "Updated plot number for the location."
+ },
+ "street": {
+ "type": "string",
+ "description": "Updated street address for the location."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "Updated city where the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Updated country where the location is situated."
+ }
+ },
+ "required": [
+ "location_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Unique identifier of the location."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the location/site."
+ },
+ "plot_no": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Plot number of the location, if provided."
+ },
+ "street": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Street address of the location, if provided."
+ },
+ "city": {
+ "type": "string",
+ "enum": [
+ "new_york",
+ "london",
+ "mumbai",
+ "tokyo",
+ "sydney"
+ ],
+ "description": "City in which the location is situated."
+ },
+ "country": {
+ "type": "string",
+ "enum": [
+ "usa",
+ "uk",
+ "india",
+ "japan",
+ "australia"
+ ],
+ "description": "Country in which the location is situated."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the location is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the location record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the location record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_product",
+ "description": "Create/register a product. Add product details. Products can be software, hardware, or services offered by the organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the product (e.g., 'Premium Support Package') (unique).",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Product category (software, hardware, or service)."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product (active or retired)."
+ },
+ "product_price": {
+ "type": "integer",
+ "description": "Price of the product in the smallest currency unit (e.g., cents)."
+ }
+ },
+ "required": [
+ "name",
+ "category",
+ "lifecycle_state"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the product."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Category of the product."
+ },
+ "product_price": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Price of the product, if provided."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the product was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the product was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_product",
+ "description": "Update a product (partial updates allowed). Products can be software, hardware, or services offered by the organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product to update."
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated product name.",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Updated product category."
+ },
+ "product_price": {
+ "type": "integer",
+ "description": "Updated product price in the smallest currency unit (e.g., cents)."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Updated lifecycle state of the product."
+ }
+ },
+ "required": [
+ "product_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the product."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the product."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Product category."
+ },
+ "product_price": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Price of the product, if defined."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Lifecycle state of the product."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the product was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the product record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "delete_products",
+ "description": "Delete products that match filters; at least one filter is required. Returns the count of deleted records.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "product_id": {
+ "type": "integer",
+ "description": "Delete by unique product identifier."
+ },
+ "name": {
+ "type": "string",
+ "description": "Delete by product name."
+ },
+ "category": {
+ "type": "string",
+ "enum": [
+ "software",
+ "hardware",
+ "service"
+ ],
+ "description": "Delete by product category."
+ },
+ "lifecycle_state": {
+ "type": "string",
+ "enum": [
+ "active",
+ "retired"
+ ],
+ "description": "Delete by lifecycle state."
+ },
+ "product_price": {
+ "type": "integer",
+ "description": "Delete by exact product price."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Delete products created before this timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Delete products created after this timestamp (YYYY-MM-DD HH:MM:SS)."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "integer",
+ "description": "Number of product records deleted."
+ }
+ }
+ }
+ },
+ {
+ "name": "register_new_installed_product",
+ "description": "Register a new installed product at an account/location. Combination of Account ID, Product ID, Serial Number should be unique.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "integer",
+ "description": "Location/site ID where the product is installed."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Owning account ID for this installed product."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID that was installed."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Unique serial number of the installed product.",
+ "minLength": 1
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Status of the installed product."
+ },
+ "warranty_end": {
+ "type": "string",
+ "description": "Warranty end date (YYYY-MM-DD)."
+ }
+ },
+ "required": [
+ "account_id",
+ "product_id",
+ "serial_number",
+ "status"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the installed product record."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account that owns this installed product."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product that was installed."
+ },
+ "location_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Location where the product is installed, if provided."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Unique serial number of the installed product."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Operational status of the installed product."
+ },
+ "warranty_end": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Warranty end date in YYYY-MM-DD format, if provided."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_installed_product_details",
+ "description": "Update an installed product (partial updates allowed). Combination of Account ID, Product ID, Serial Number should be unique.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique installed product ID (required)."
+ },
+ "location_id": {
+ "type": "integer",
+ "description": "Location/site ID where the product is installed."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Owning account ID for this installed product."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID that was installed."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Unique serial number of the installed product.",
+ "minLength": 1
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Status of the installed product."
+ },
+ "warranty_end": {
+ "type": "string",
+ "description": "Warranty end date (YYYY-MM-DD)."
+ }
+ },
+ "required": [
+ "installed_product_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Unique identifier of the installed product record."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account that owns this installed product."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product associated with this installed product."
+ },
+ "location_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Location where the product is installed, if provided."
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Unique serial number of the installed product."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "repair",
+ "retired"
+ ],
+ "description": "Operational status of the installed product."
+ },
+ "warranty_end": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Warranty end date in YYYY-MM-DD format, if available."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp when this installed product record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp when this installed product was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "enlist_new_contract",
+ "description": "Create a new contract for an account. Contracts define the terms of service, support, or warranty agreements between the organization and its customers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account the contract is associated with."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Type of contract to create."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Price value for the contract."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Initial status of the contract."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Start date of the contract (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "End date of the contract (YYYY-MM-DD)."
+ }
+ },
+ "required": [
+ "account_id",
+ "contract_type",
+ "status",
+ "start_date",
+ "end_date"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "integer",
+ "description": "Unique identifier of the newly created contract."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account the contract is associated with."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Type of contract."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Current status of the created contract."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Price value for the contract."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Start date of the contract (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "End date of the contract (YYYY-MM-DD)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contract record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contract record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_contract",
+ "description": "Update an existing contract (partial updates allowed). Contracts define the terms of service, support, or warranty agreements between the organization and its customers.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contract to update."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Update the account ID associated with this contract."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Update the price value of the contract."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Update the contract type."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Update the contract\u2019s status."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Update the contract\u2019s start date (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "Update the contract\u2019s end date (YYYY-MM-DD)."
+ }
+ },
+ "required": [
+ "contract_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "contract_id": {
+ "type": "integer",
+ "description": "Unique identifier of the contract."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the account the contract is associated with."
+ },
+ "contract_type": {
+ "type": "string",
+ "enum": [
+ "support",
+ "warranty",
+ "subscription"
+ ],
+ "description": "Type of contract."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "active",
+ "suspended",
+ "expired"
+ ],
+ "description": "Current status of the contract."
+ },
+ "contract_price": {
+ "type": "integer",
+ "description": "Price value of the contract."
+ },
+ "start_date": {
+ "type": "string",
+ "description": "Start date of the contract (YYYY-MM-DD)."
+ },
+ "end_date": {
+ "type": "string",
+ "description": "End date of the contract (YYYY-MM-DD)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contract record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the contract record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_entitlement",
+ "description": "Create a new entitlement. Entitlements define the support and service levels provided to an account for specific products or contracts.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID to which the entitlement belongs."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID associated with the entitlement (optional)."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Contract ID linked to this entitlement."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level provided under the entitlement."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Coverage hours provided (8x5, 12x6, 24x7)."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Maximum number of support cases allowed per month."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the entitlement is active (true) or inactive (false)."
+ }
+ },
+ "required": [
+ "account_id",
+ "support_level",
+ "active"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {
+ "type": "integer",
+ "description": "Unique identifier of the entitlement."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID to which the entitlement belongs."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID associated with the entitlement (null means all products)."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Contract ID linked to this entitlement."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level provided under the entitlement."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Coverage hours of the entitlement."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Maximum allowed support cases per month."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the entitlement is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the entitlement was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the entitlement was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_entitlement",
+ "description": "Update an entitlement (partial updates allowed). Entitlements define the support and service levels provided to an account for specific products or contracts.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {
+ "type": "integer",
+ "description": "Unique ID of the entitlement to update."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Update the associated account ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Update the product ID linked to the entitlement."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Update the contract ID linked to the entitlement."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Update the support level."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Update the coverage hours."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Update the maximum number of support cases per month."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Set entitlement status as active (true) or inactive (false)."
+ }
+ },
+ "required": [
+ "entitlement_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {
+ "type": "integer",
+ "description": "Unique identifier of the entitlement."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with this entitlement."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID linked to the entitlement (null means all products)."
+ },
+ "contract_id": {
+ "type": "integer",
+ "description": "Contract ID associated with the entitlement."
+ },
+ "support_level": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "premium",
+ "enterprise"
+ ],
+ "description": "Support level assigned to the entitlement."
+ },
+ "coverage_hours": {
+ "type": "string",
+ "enum": [
+ "h8x5",
+ "h12x6",
+ "h24x7"
+ ],
+ "description": "Coverage hours defined for the entitlement."
+ },
+ "max_cases_per_month": {
+ "type": "integer",
+ "description": "Maximum number of support cases allowed per month."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the entitlement is active (true) or inactive (false)."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the entitlement record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the entitlement record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "add_new_sla_definition",
+ "description": "Create an SLA definition. SLA definitions specify the service level agreements for support cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "Metric type: 'response' for response SLAs, 'resolution' for resolution SLAs."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target SLA duration in minutes."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Name of the SLA definition."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether the SLA timer pauses when case status is pending."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level to which the SLA applies."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Flag indicating whether this SLA definition is active."
+ }
+ },
+ "required": [
+ "metric",
+ "name",
+ "target_mins",
+ "pause_on_pending",
+ "active"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Unique identifier of the SLA definition."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition (ensured to be unique)."
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "Metric type for the SLA: 'response' or 'resolution'."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target SLA duration in minutes."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether the SLA timer pauses while the case is in a pending state."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level this SLA definition applies to."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA definition is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA definition record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA definition record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_sla_definition",
+ "description": "Update an SLA definition (partial updates). SLA definitions specify the service level agreements for support cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Unique ID of the SLA definition to update."
+ },
+ "name": {
+ "type": "string",
+ "description": "New name for the SLA definition.",
+ "minLength": 1
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "Update the metric type."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Update the target SLA duration in minutes."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Update whether SLA timer pauses when status is pending."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Update the priority level this SLA applies to."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Update the SLA definition\u2019s active status."
+ }
+ },
+ "required": [
+ "sla_def_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Unique identifier of the SLA definition."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition."
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "Metric type for the SLA."
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target duration for the SLA in minutes."
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA timer pauses when the case is pending."
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level that this SLA definition applies to."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether this SLA definition is active."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA definition was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA definition was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "create_new_case",
+ "description": "Create a case with all case related details. Returns the created case record. A case represents a customer issue or request that needs to be tracked and resolved.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with the case."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact ID who raised the case."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID related to the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Installed product ID associated with the case."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was raised."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Initial state of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 500,
+ "description": "Short description summarizing the case issue."
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Reason for escalation if applicable.",
+ "minLength": 1
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Initial reopen count for the case."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Closed date if state is closed (YYYY-MM-DD HH:MM:SS)."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID responsible for the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "User ID assigned to the case."
+ }
+ },
+ "required": [
+ "account_id",
+ "contact_id",
+ "channel",
+ "priority",
+ "state",
+ "short_description"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "number": {
+ "type": "string",
+ "description": "System-generated unique case number."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with the case."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact ID who raised the case."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID related to the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Installed product ID associated with the case."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was raised."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Current state of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description summarizing the case issue."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID responsible for the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "User ID assigned to the case."
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Reason for escalation if applicable."
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Number of times the case has been reopened."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case record was last updated."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case was closed, if applicable."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_case",
+ "description": "Update an existing case (partial updates). A case represents a customer issue or request that needs to be tracked and resolved.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case to update."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Update the associated account ID."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Update the associated contact ID."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Update the product ID associated with the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Update the installed product ID."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Update the channel used to create the case."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Update the case priority."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Update the case state."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Update the case short description.",
+ "minLength": 1,
+ "maxLength": 500
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Update whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Update the escalation reason.",
+ "minLength": 1
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Update the reopen count."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Update the closed date (YYYY-MM-DD HH:MM:SS)."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Update the assignment group ID."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "Update the assigned user ID."
+ }
+ },
+ "required": [
+ "case_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "number": {
+ "type": "string",
+ "description": "System-generated unique case number."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Account ID associated with the case."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Contact ID who raised the case."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Product ID related to the case."
+ },
+ "installed_product_id": {
+ "type": "integer",
+ "description": "Installed product ID associated with the case."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the case was raised."
+ },
+ "priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority level of the case."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "new",
+ "in_progress",
+ "pending",
+ "resolved",
+ "closed",
+ "canceled"
+ ],
+ "description": "Current state of the case."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description summarizing the case issue."
+ },
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID responsible for the case."
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "User ID assigned to the case."
+ },
+ "escalation": {
+ "type": "boolean",
+ "description": "Whether the case is escalated."
+ },
+ "escalation_reason": {
+ "type": "string",
+ "enum": [
+ "urgency",
+ "vip",
+ "impact",
+ "breach_risk",
+ "customer_request"
+ ],
+ "description": "Reason for escalation if applicable."
+ },
+ "reopen_count": {
+ "type": "integer",
+ "description": "Number of times the case has been reopened."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case record was last updated."
+ },
+ "closed_on": {
+ "type": "string",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the case was closed, if applicable."
+ }
+ }
+ }
+ },
+ {
+ "name": "link_new_case_sla",
+ "description": "Create a case_sla linkage record. A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case being linked to an SLA."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "ID of the SLA definition to apply."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Initial stage of SLA tracking."
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Start time of SLA tracking. If omitted, defaults to current timestamp."
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Expected SLA breach timestamp (YYYY-MM-DD HH:MM:SS)."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Whether the SLA was already breached at creation (true/false)."
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Completion timestamp if the SLA is already completed."
+ }
+ },
+ "required": [
+ "case_id",
+ "sla_def_id",
+ "stage"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_sla linkage record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case linked to this SLA."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "ID of the SLA definition applied to the case."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Current stage of SLA tracking for this case."
+ },
+ "start_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp when SLA tracking started for the case."
+ },
+ "breach_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Expected or actual SLA breach timestamp, if set."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA has been breached (true/false)."
+ },
+ "completed_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the SLA was completed, if applicable."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_case_sla_details",
+ "description": "Update a case_sla record (partial updates). A case_sla links a support case to a specific SLA definition, tracking the SLA status for that case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_sla record to update."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Update the case ID linked to the SLA."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Update the SLA definition ID."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Update the stage of SLA tracking."
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Update the SLA start time."
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Update the expected breach time."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Update whether the SLA is breached."
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Update the completion time."
+ }
+ },
+ "required": [
+ "case_sla_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_sla record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the case associated with this SLA record."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "ID of the SLA definition applied to the case."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Current stage of SLA tracking."
+ },
+ "start_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp when SLA tracking began."
+ },
+ "breach_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Expected or actual SLA breach timestamp."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Indicates whether the SLA has been breached (true/false)."
+ },
+ "completed_time": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp when SLA tracking was completed, if applicable."
+ }
+ }
+ }
+ },
+ {
+ "name": "delete_case_slas",
+ "description": "Delete case_sla rows that match filters; at least one filter required.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_sla_id": {
+ "type": "integer",
+ "description": "Delete by case_sla record ID."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Delete by linked case ID."
+ },
+ "sla_def_id": {
+ "type": "integer",
+ "description": "Delete by SLA definition ID."
+ },
+ "stage": {
+ "type": "string",
+ "enum": [
+ "in_progress",
+ "paused",
+ "completed",
+ "canceled"
+ ],
+ "description": "Delete by SLA stage."
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Delete by SLA start time."
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Delete by SLA breach time."
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Delete by SLA breach status."
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Delete by SLA completion time."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "integer",
+ "description": "Number of case_sla records deleted based on the provided filters."
+ }
+ }
+ }
+ },
+ {
+ "name": "register_new_interaction",
+ "description": "Create an interaction; account/contact/case/interacted_user are optional FKs. Returns the created interaction record. An interaction represents a communication or engagement with a customer through various channels.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the interaction occurred."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the related account, if applicable."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "ID of the related contact, if applicable."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the related case, if applicable."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "User ID of the agent or person who interacted."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Current status of the interaction."
+ },
+ "started_at": {
+ "type": "string",
+ "description": "Start time of the interaction (defaults to current timestamp if not provided)."
+ },
+ "ended_at": {
+ "type": "string",
+ "description": "End time of the interaction, if already finished."
+ }
+ },
+ "required": [
+ "channel",
+ "status"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "interaction_id": {
+ "type": "integer",
+ "description": "Unique identifier of the interaction."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the interaction occurred."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the related account, if applicable."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "ID of the related contact, if applicable."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the related case, if applicable."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "User ID of the agent or person who handled the interaction."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Current status of the interaction."
+ },
+ "started_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction started."
+ },
+ "ended_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction ended, if applicable."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction record was created."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_interaction",
+ "description": "Update an interaction (partial updates). An interaction represents a communication or engagement with a customer through various channels.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "interaction_id": {
+ "type": "integer",
+ "description": "Unique identifier of the interaction to update."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Update the interaction channel."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "Update the related account ID."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "Update the related contact ID."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Update the related case ID."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "Update the user ID of the interacting person."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Update the interaction status."
+ },
+ "started_at": {
+ "type": "string",
+ "description": "Update the interaction start time."
+ },
+ "ended_at": {
+ "type": "string",
+ "description": "Update the interaction end time."
+ }
+ },
+ "required": [
+ "interaction_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "interaction_id": {
+ "type": "integer",
+ "description": "Unique identifier of the interaction."
+ },
+ "channel": {
+ "type": "string",
+ "enum": [
+ "web",
+ "email",
+ "phone",
+ "chat",
+ "social",
+ "alert",
+ "community"
+ ],
+ "description": "Channel through which the interaction occurred."
+ },
+ "account_id": {
+ "type": "integer",
+ "description": "ID of the related account, if applicable."
+ },
+ "contact_id": {
+ "type": "integer",
+ "description": "ID of the related contact, if applicable."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "ID of the related case, if applicable."
+ },
+ "interacted_user": {
+ "type": "integer",
+ "description": "User ID of the agent or person who handled the interaction."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "open",
+ "handled",
+ "closed"
+ ],
+ "description": "Current status of the interaction."
+ },
+ "started_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction started."
+ },
+ "ended_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction ended, if applicable."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the interaction record was created."
+ }
+ }
+ }
+ },
+ {
+ "name": "create_knowledge",
+ "description": "Create a knowledge article (kb_number is auto-generated). Returns the created knowledge article record. A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Title of the knowledge article.",
+ "minLength": 1
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Lifecycle state of the article."
+ },
+ "body": {
+ "type": "string",
+ "description": "Body of the knowledge article."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Who can view the article: internal staff or external customers."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "ID of the related product, if applicable."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "User ID of the article owner/author."
+ }
+ },
+ "required": [
+ "title",
+ "state",
+ "body",
+ "visibility",
+ "owner_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "System-generated unique knowledge article number (e.g., KB000001)."
+ },
+ "title": {
+ "type": "string",
+ "description": "Title of the knowledge article."
+ },
+ "body": {
+ "type": "string",
+ "description": "Full body/content of the knowledge article."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Lifecycle state of the article."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Visibility of the article: internal staff or external customers."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "ID of the related product, if applicable."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "User ID of the article owner/author."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the knowledge article record was created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the knowledge article record was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_knowledge",
+ "description": "Update a knowledge article (partial updates allowed). A knowledge article is a documented piece of information that provides solutions, guidelines, or answers to common questions for customers or internal staff.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article to update."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Knowledge base number (system-generated unique reference)."
+ },
+ "title": {
+ "type": "string",
+ "description": "Update the title of the article.",
+ "minLength": 1
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Update the lifecycle state of the article."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Update the visibility of the article."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "Update the related product ID."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "Update the user ID of the article owner/author."
+ }
+ },
+ "required": [
+ "knowledge_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the updated knowledge article."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Knowledge base number (unique system-generated reference)."
+ },
+ "title": {
+ "type": "string",
+ "description": "Title of the knowledge article."
+ },
+ "body": {
+ "type": "string",
+ "description": "Full body/content of the knowledge article."
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "description": "Lifecycle state of the article."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "description": "Visibility of the article: internal staff or external customers."
+ },
+ "product_id": {
+ "type": "integer",
+ "description": "ID of the related product associated with this article."
+ },
+ "owner_id": {
+ "type": "integer",
+ "description": "User ID of the article owner/author."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the knowledge article was originally created."
+ },
+ "sys_updated_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the knowledge article was last updated."
+ }
+ }
+ }
+ },
+ {
+ "name": "link_case_knowledge",
+ "description": "Link a case to a knowledge article. A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case being linked."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article to link."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Purpose of the knowledge article in context of the case: suggested, applied, or used as resolution."
+ }
+ },
+ "required": [
+ "case_id",
+ "knowledge_id",
+ "used_as"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked case."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Purpose of the knowledge article in the context of the case (suggested, applied, or resolution)."
+ }
+ }
+ }
+ },
+ {
+ "name": "updated_linked_case_knowledge",
+ "description": "Update a case_knowledge linkage (partial updates). A case_knowledge linkage associates a support case with a specific knowledge article, indicating how the article is relevant to the case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked case."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Updated purpose of the linkage."
+ }
+ },
+ "required": [
+ "case_kb_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked case."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the linked knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Current purpose of the knowledge article in the context of the case."
+ }
+ }
+ }
+ },
+ {
+ "name": "delete_case_knowledge_linkages",
+ "description": "Delete case_knowledge rows that match filters (at least one filter required).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_kb_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case_knowledge linkage."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Unique identifier of the case."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Unique identifier of the knowledge article."
+ },
+ "used_as": {
+ "type": "string",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "description": "Filter by purpose of linkage."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "integer",
+ "description": "Number of case_knowledge linkage records deleted based on the provided filters."
+ }
+ }
+ }
+ },
+ {
+ "name": "send_notification",
+ "description": "Create a notification for a case (optionally tied to knowledge). Returns the created notification record. A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID this notification is related to."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Optional knowledge article ID linked to this notification."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address of the notification.",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type of notification being sent."
+ }
+ },
+ "required": [
+ "case_id",
+ "email",
+ "type"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the created notification record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID this notification is related to."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID linked to this notification, if any."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address of the notification."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type/category of the notification."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delivery status of the notification."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the notification record was created."
+ }
+ }
+ }
+ },
+ {
+ "name": "update_notification",
+ "description": "Update an existing notification (partial updates). A notification represents a message sent to a customer or user regarding updates, alerts, or information related to a support case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the notification to update."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID associated with this notification."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID linked to this notification."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address for the notification.",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type of notification."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delivery status of the notification."
+ }
+ },
+ "required": [
+ "notification_id"
+ ]
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the updated notification record."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID associated with this notification."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID linked to this notification, if any."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address of the notification."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type/category of the notification."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delivery status of the notification."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp (YYYY-MM-DD HH:MM:SS) when the notification record was created."
+ }
+ }
+ }
+ },
+ {
+ "name": "delete_notifications",
+ "description": "Delete notifications by filters (at least one required). Supports created_before/after.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Unique ID of the notification to delete."
+ },
+ "case_id": {
+ "type": "integer",
+ "description": "Case ID filter for deleting notifications."
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID filter for deleting notifications."
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email filter for deleting notifications."
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "next_steps",
+ "other"
+ ],
+ "description": "Type of notifications to delete."
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "success",
+ "failed"
+ ],
+ "description": "Delete only notifications with this delivery status."
+ },
+ "sys_created_on": {
+ "type": "string",
+ "description": "Exact creation timestamp filter."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Delete notifications created before this date."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Delete notifications created after this date."
+ }
+ }
+ },
+ "outputSchema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "integer",
+ "description": "Number of notification records deleted based on the provided filters."
+ }
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/drive.json b/resources_servers/enterpriseops_gym/data/tools/drive.json
new file mode 100644
index 0000000000..ddbb9da87a
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/drive.json
@@ -0,0 +1,3168 @@
+{
+ "gym_name": "gym-google-drive-mcp",
+ "gym_url": "http://localhost:8009",
+ "snapshot_at": "2026-07-07T18:18:29.356956+00:00",
+ "tools": [
+ {
+ "name": "get_operations",
+ "description": "Gets the latest state of a long-running operation. Clients can use this method to poll the operation result at intervals as recommended by the API service. Essential for monitoring export, download, backup, and other long-running operations in Google Drive. Use this to check operation status, retrieve operation results, or monitor operation progress.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the operation resource (required). Format: operations/{operation_id}",
+ "pattern": "^operations/.+",
+ "minLength": 11,
+ "examples": [
+ "operations/download_file_1",
+ "operations/export_file_2",
+ "operations/backup_drive_1"
+ ]
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_drive",
+ "description": "Gets a shared drive's metadata by ID. Use this to retrieve information about a shared drive, such as its name, capabilities, and restrictions.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive.",
+ "minLength": 1,
+ "examples": [
+ "550e8400-e29b-41d4-a716-446655440000"
+ ]
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator."
+ }
+ },
+ "required": [
+ "driveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "hide_drives",
+ "description": "Hides a shared drive from the default view. For more information, see Manage shared drives. This operation makes the drive invisible in the default Drive interface but does not affect access permissions. Only users with organizer role can hide drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive to hide.",
+ "minLength": 1,
+ "examples": [
+ "550e8400-e29b-41d4-a716-446655440000"
+ ]
+ }
+ },
+ "required": [
+ "driveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "unhide_drives",
+ "description": "Restores a shared drive to the default view. For more information, see Manage shared drives. This operation makes a previously hidden drive visible again in the default Drive interface. Only users with organizer role can unhide drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive to unhide.",
+ "minLength": 1,
+ "examples": [
+ "550e8400-e29b-41d4-a716-446655440000"
+ ]
+ }
+ },
+ "required": [
+ "driveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_drive",
+ "description": "Creates a shared drive. Note: Restrictions cannot be set during creation - use drives.update to add restrictions after creation. For more information, see Manage shared drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "requestId": {
+ "type": "string",
+ "description": "An ID, such as a random UUID, which uniquely identifies this user's request for idempotent creation of a shared drive.",
+ "minLength": 1,
+ "examples": [
+ "550e8400-e29b-41d4-a716-446655440000"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the shared drive.",
+ "minLength": 1,
+ "examples": [
+ "My Shared Drive"
+ ]
+ },
+ "colorRgb": {
+ "type": "string",
+ "description": "The color of the shared drive as an RGB hex string.",
+ "pattern": "^#[0-9A-Fa-f]{6}$",
+ "examples": [
+ "#FF0000",
+ "#00FF00",
+ "#0000FF"
+ ]
+ },
+ "themeId": {
+ "type": "string",
+ "description": "The ID of the theme from which the background image and color will be set. The set of possible driveThemes can be retrieved from a drive.about.get response. When not specified on a drive.drives.create request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set colorRgb.",
+ "examples": [
+ "theme_1",
+ "theme_2"
+ ]
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether the shared drive is hidden from default view.",
+ "default": false
+ }
+ },
+ "required": [
+ "requestId",
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_drive",
+ "description": "Permanently deletes a shared drive for which the user is an organizer. The shared drive cannot contain any untrashed items. For more information, see Manage shared drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive.",
+ "minLength": 1,
+ "examples": [
+ "0AOp1234567890abcdef"
+ ]
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.",
+ "default": false
+ },
+ "allowItemDeletion": {
+ "type": "boolean",
+ "description": "Whether any items inside the shared drive should also be deleted. This option is only supported when useDomainAdminAccess is also set to true.",
+ "default": false
+ }
+ },
+ "required": [
+ "driveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_drives",
+ "description": "Lists the user's shared drives. This method accepts the q parameter, which is a search query combining one or more search terms. For more information, see the Search for shared drives guide.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "pageSize": {
+ "type": "integer",
+ "description": "Maximum number of shared drives to return per page.",
+ "minimum": 1,
+ "maximum": 100,
+ "default": 100,
+ "examples": [
+ 10,
+ 25,
+ 50,
+ 100
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Page token for shared drives.",
+ "examples": [
+ "0",
+ "100",
+ "200"
+ ]
+ },
+ "q": {
+ "type": "string",
+ "description": "Query string for searching shared drives. For more information, see the Search for shared drives guide.",
+ "examples": [
+ "name contains 'Project'",
+ "hidden = false",
+ "createdTime > '2023-01-01T00:00:00Z'"
+ ]
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator; if set to true, then all shared drives of the domain in which the requester is an administrator are returned.",
+ "default": false
+ }
+ },
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_drives",
+ "description": "Updates the metadata for a shared drive. For more information, see Manage shared drives. This method supports patch semantics and allows updating drive properties like name, color, theme, restrictions, and more.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive.",
+ "minLength": 1,
+ "examples": [
+ "0AOp1234567890abcdef"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the shared drive.",
+ "minLength": 1,
+ "examples": [
+ "My Updated Drive",
+ "Team Collaboration Drive"
+ ]
+ },
+ "colorRgb": {
+ "type": "string",
+ "description": "The color of the shared drive as an RGB hex string.",
+ "pattern": "^#[0-9A-Fa-f]{6}$",
+ "examples": [
+ "#FF0000",
+ "#00FF00",
+ "#0000FF"
+ ]
+ },
+ "themeId": {
+ "type": "string",
+ "description": "The ID of the theme from which the background image and color will be set. The set of possible driveThemes can be retrieved from a drive.about.get response. This is a write-only field; it can only be set on requests that don't set colorRgb or backgroundImageFile.",
+ "examples": [
+ "theme_1",
+ "theme_2"
+ ]
+ },
+ "backgroundImageFile": {
+ "type": "object",
+ "description": "An image file and cropping parameters from which a background image for this shared drive is set. This is a write only field; it can only be set on drive.drives.update requests that don't set themeId. When specified, all fields of the backgroundImageFile must be set.",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of an image file in Google Drive to use for the background image.",
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ]
+ },
+ "xCoordinate": {
+ "type": "number",
+ "description": "The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the horizontal distance from the left side of the entire image to the left side of the cropping area divided by the width of the entire image.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.1,
+ 0.5,
+ 0.9
+ ]
+ },
+ "yCoordinate": {
+ "type": "number",
+ "description": "The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the vertical distance from the top side of the entire image to the top side of the cropping area divided by the height of the entire image.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.1,
+ 0.5,
+ 0.9
+ ]
+ },
+ "width": {
+ "type": "number",
+ "description": "The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image. The height is computed by applying a width to height aspect ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and 144 pixels high.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.5,
+ 0.8,
+ 1.0
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "xCoordinate",
+ "yCoordinate",
+ "width"
+ ]
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether the shared drive is hidden from default view.",
+ "default": false
+ },
+ "restrictions": {
+ "type": "object",
+ "description": "A set of restrictions that apply to this shared drive. These restrictions control sharing and access behavior for the shared drive.",
+ "properties": {
+ "adminManagedRestrictions": {
+ "type": "boolean",
+ "description": "Whether administrative privileges on this shared drive are required to modify restrictions.",
+ "default": false
+ },
+ "copyRequiresWriterPermission": {
+ "type": "boolean",
+ "description": "Whether the options to copy, print, or download files inside this shared drive should be disabled for readers and commenters.",
+ "default": false
+ },
+ "domainUsersOnly": {
+ "type": "boolean",
+ "description": "Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs.",
+ "default": false
+ },
+ "driveMembersOnly": {
+ "type": "boolean",
+ "description": "Whether access to items inside this shared drive is restricted to members of this shared drive.",
+ "default": false
+ }
+ }
+ },
+ "sharingFoldersRequiresOrganizerPermission": {
+ "type": "boolean",
+ "description": "If true, only users with the organizer role can share folders.",
+ "default": false
+ },
+ "downloadRestrictedForReaders": {
+ "type": "boolean",
+ "description": "Whether download is restricted for readers.",
+ "default": false
+ },
+ "downloadRestrictedForWriters": {
+ "type": "boolean",
+ "description": "Whether download is restricted for writers.",
+ "default": false
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.",
+ "default": false
+ }
+ },
+ "required": [
+ "driveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_comments",
+ "description": "Gets a comment by ID from a Google Drive file. Retrieves detailed information about a specific comment including content, author, creation time, and resolved status. Essential for reading comment discussions and managing file collaboration.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment to retrieve (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "includeDeleted": {
+ "type": "boolean",
+ "description": "Whether to include deleted comments in the response (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_comments",
+ "description": "Creates a new comment on a Google Drive file. Adds a comment with specified content and optional anchor to a specific location in the document. Essential for file collaboration and feedback workflows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to comment on (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "content": {
+ "type": "string",
+ "description": "The plain text content of the comment (required)",
+ "minLength": 1,
+ "maxLength": 8192,
+ "examples": [
+ "Please review this section",
+ "Great work on this document!",
+ "Could you clarify this point?"
+ ]
+ },
+ "anchor": {
+ "type": "string",
+ "description": "A region of the document represented as a JSON string (optional). For anchored comments on supported file types.",
+ "examples": [
+ "{\"r\":\"kix.abc123\"}",
+ "{\"line\": {\"startLineNumber\": 5, \"endLineNumber\": 7}}"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "content"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_comments",
+ "description": "Deletes a comment from a Google Drive file. Permanently removes the specified comment and all its replies. Only the comment author or file owner can delete comments. Essential for managing file discussions and removing inappropriate content.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment to delete (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_comments",
+ "description": "Lists all comments on a Google Drive file. Retrieves a paginated list of comments with their content, authors, timestamps, and replies. Essential for viewing all file discussions and comment threads.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to list comments for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "includeDeleted": {
+ "type": "boolean",
+ "description": "Whether to include deleted comments in the response (optional, default: false)",
+ "default": false
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of comments to return per page (optional, default: 100, max: 100)",
+ "minimum": 1,
+ "maximum": 100,
+ "default": 100
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request (optional)",
+ "examples": [
+ "0",
+ "100",
+ "200"
+ ]
+ },
+ "startModifiedTime": {
+ "type": "string",
+ "description": "RFC 3339 date-time to filter comments modified after this time (optional)",
+ "examples": [
+ "2024-01-01T00:00:00Z",
+ "2024-01-15T10:30:00Z"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "copy_files",
+ "description": "Creates a copy of a file and applies any requested updates with patch semantics. For more information, see Create and manage files. Essential for duplicating files, creating templates, and file backup workflows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to copy (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the copied file (optional)",
+ "examples": [
+ "Copy of My Document",
+ "Backup - Presentation"
+ ]
+ },
+ "parents": {
+ "type": "array",
+ "description": "A list of parent folder IDs for the copied file (optional)",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ],
+ [
+ "folder1",
+ "folder2"
+ ]
+ ]
+ },
+ "keepRevisionForever": {
+ "type": "boolean",
+ "description": "Whether to set the keepForever field in the new head revision. This is only applicable to files with binary content in Google Drive.",
+ "default": false
+ },
+ "ocrLanguage": {
+ "type": "string",
+ "description": "A language hint for OCR processing during image import (ISO 639-1 code)",
+ "examples": [
+ "en",
+ "es",
+ "fr",
+ "de"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives",
+ "default": false
+ },
+ "ignoreDefaultVisibility": {
+ "type": "boolean",
+ "description": "Whether to ignore the domain's default visibility settings for the created file",
+ "default": false
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported",
+ "enum": [
+ "published"
+ ],
+ "examples": [
+ "published"
+ ]
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response",
+ "examples": [
+ "label1,label2,label3"
+ ]
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the file (optional)",
+ "examples": [
+ "application/vnd.google-apps.document",
+ "application/pdf",
+ "text/plain"
+ ]
+ },
+ "starred": {
+ "type": "boolean",
+ "description": "Whether the user has starred the file (optional)",
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description of the file (optional)",
+ "examples": [
+ "A backup copy of the presentation",
+ "Template document for project planning"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_comments",
+ "description": "Updates an existing comment on a Google Drive file. Modifies comment content, anchor position, or other properties. Only the comment author can update their comments. Essential for editing comments and correcting mistakes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment to update (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "content": {
+ "type": "string",
+ "description": "The updated plain text content of the comment (optional)",
+ "minLength": 1,
+ "examples": [
+ "Updated comment content",
+ "This is the revised comment"
+ ]
+ },
+ "anchor": {
+ "type": "string",
+ "description": "A region of the document represented as a JSON string (optional). For anchored comments on supported file types.",
+ "examples": [
+ "{\"r\":\"kix.abc123\"}",
+ "{\"line\": {\"startLineNumber\": 5, \"endLineNumber\": 7}}"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_permission",
+ "description": "Creates a permission for a file or shared drive. Grants access to users, groups, domains, or anyone on the internet. Essential for sharing files and managing access control in Google Drive.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file or shared drive to grant permission for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "role": {
+ "type": "string",
+ "description": "The role granted by this permission (required)",
+ "enum": [
+ "owner",
+ "organizer",
+ "fileOrganizer",
+ "writer",
+ "commenter",
+ "reader"
+ ],
+ "examples": [
+ "reader",
+ "writer",
+ "commenter"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of the grantee (required)",
+ "enum": [
+ "user",
+ "group",
+ "domain",
+ "anyone"
+ ],
+ "examples": [
+ "user",
+ "group",
+ "anyone"
+ ]
+ },
+ "emailAddress": {
+ "type": "string",
+ "description": "The email address of the user or group to grant permission to (required for user/group types)",
+ "format": "email",
+ "examples": [
+ "user@example.com",
+ "team@company.com"
+ ]
+ },
+ "domain": {
+ "type": "string",
+ "description": "The domain to grant permission to (required for domain type)",
+ "examples": [
+ "example.com",
+ "company.org"
+ ]
+ },
+ "allowFileDiscovery": {
+ "type": "boolean",
+ "description": "Whether the permission allows the file to be discovered through search (optional, default: false)",
+ "default": false
+ },
+ "sendNotificationEmail": {
+ "type": "boolean",
+ "description": "Whether to send a notification email when sharing to users or groups. This defaults to true for users and groups, and is not allowed for other requests. It must not be disabled for ownership transfers (optional, default: true)",
+ "default": true
+ },
+ "expirationTime": {
+ "type": "string",
+ "description": "The expiration time of the permission (optional)",
+ "examples": [
+ "2024-01-01T00:00:00Z",
+ "2024-01-15T10:30:00Z"
+ ]
+ },
+ "view": {
+ "type": "string",
+ "description": "The view of the permission (optional)",
+ "enum": [
+ "published"
+ ],
+ "examples": [
+ "published"
+ ]
+ },
+ "pendingOwner": {
+ "type": "boolean",
+ "description": "Whether the permission is pending owner (optional, default: false)",
+ "default": false
+ },
+ "inheritedPermissionsDisabled": {
+ "type": "boolean",
+ "description": "Whether the permission is inherited permissions disabled (optional, default: false)",
+ "default": false
+ },
+ "emailMessage": {
+ "type": "string",
+ "description": "A plain text custom message to include in the notification email (optional)",
+ "maxLength": 4096,
+ "examples": [
+ "Please review this document",
+ "Sharing this file with the team"
+ ]
+ },
+ "moveToNewOwnersRoot": {
+ "type": "boolean",
+ "description": "This parameter only takes effect if the item isn't in a shared drive and the request is attempting to transfer the ownership of the item. If set to true, the item is moved to the new owner's My Drive root folder and all prior parents removed. If set to false, parents aren't changed (optional, default: false)",
+ "default": false
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: false)",
+ "default": false
+ },
+ "transferOwnership": {
+ "type": "boolean",
+ "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect (optional, default: false)",
+ "default": false
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator. If set to true, and if the following additional conditions are met, the requester is granted access: The file ID parameter refers to a shared drive. The requester is an administrator of the domain to which the shared drive belongs (optional, default: false)",
+ "default": false
+ },
+ "enforceExpansiveAccess": {
+ "type": "boolean",
+ "description": "Whether the request should enforce expansive access rules (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "role",
+ "type"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_permission",
+ "description": "Deletes a permission from a file or shared drive. Removes access for the specified permission holder. Only the file owner or permission holder can delete permissions.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file or shared drive containing the permission (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "permissionId": {
+ "type": "string",
+ "description": "The ID of the permission to delete (required)",
+ "minLength": 1,
+ "examples": [
+ "anyoneWithLink",
+ "0123456789abcdef",
+ "user:alice@example.com"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "permissionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_permission",
+ "description": "Gets a specific permission by ID from a file or shared drive. Retrieves detailed information about who has access and what level of access they have.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file or shared drive containing the permission (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "permissionId": {
+ "type": "string",
+ "description": "The ID of the permission to retrieve (required)",
+ "minLength": 1,
+ "examples": [
+ "anyoneWithLink",
+ "0123456789abcdef",
+ "user:alice@example.com"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "permissionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_permission",
+ "description": "Lists the permissions for a file or shared drive. Returns all users, groups, and domains that have access to the file, along with their permission levels.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file or shared drive to list permissions for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include. Only 'published' is supported (optional)",
+ "enum": [
+ "published"
+ ],
+ "examples": [
+ "published"
+ ]
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of permissions to return per page. When not set for files in a shared drive, at most 100 results will be returned. When not set for files that are not in a shared drive, the entire list will be returned (optional, max: 100)",
+ "minimum": 1,
+ "maximum": 100,
+ "examples": [
+ 10,
+ 25,
+ 50,
+ 100
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page. This should be set to the value of nextPageToken from the previous response (optional)",
+ "examples": [
+ "CAISBggBEAEYAg",
+ "CAISBggBEAIYAw"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: false)",
+ "default": false
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator. If set to true, and if the following additional conditions are met, the requester is granted access: The file ID parameter refers to a shared drive. The requester is an administrator of the domain to which the shared drive belongs (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_permission",
+ "description": "Updates an existing permission for a file or shared drive. Modifies the role or other settings for an existing permission holder.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file or shared drive containing the permission (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "permissionId": {
+ "type": "string",
+ "description": "The ID of the permission to update (required)",
+ "minLength": 1,
+ "examples": [
+ "anyoneWithLink",
+ "0123456789abcdef",
+ "user:alice@example.com"
+ ]
+ },
+ "role": {
+ "type": "string",
+ "description": "The role granted by this permission (optional, if updating). According to API docs, only 'role' is writable in the request body. Expiration can be removed using the 'removeExpiration' query parameter.",
+ "enum": [
+ "owner",
+ "organizer",
+ "fileOrganizer",
+ "writer",
+ "commenter",
+ "reader"
+ ],
+ "examples": [
+ "reader",
+ "writer",
+ "commenter"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: false)",
+ "default": false
+ },
+ "transferOwnership": {
+ "type": "boolean",
+ "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer (optional, default: false)",
+ "default": false
+ },
+ "useDomainAdminAccess": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator (optional, default: false)",
+ "default": false
+ },
+ "removeExpiration": {
+ "type": "boolean",
+ "description": "Whether to remove the expiration date (optional, default: false)",
+ "default": false
+ },
+ "enforceExpansiveAccess": {
+ "type": "boolean",
+ "description": "Whether the request should enforce expansive access rules (optional, default: false)",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "permissionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_accessproposals",
+ "description": "Retrieves an access proposal by ID. For more information, see Manage pending access proposals.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "Required. The ID of the item the request is on.",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "proposalId": {
+ "type": "string",
+ "description": "Required. The ID of the access proposal to resolve.",
+ "minLength": 1,
+ "examples": [
+ "01JBQM3K8TGHZX9RNVQM5Y2PAZ",
+ "01JBQM3K8TGHZX9RNVQM5Y2PB0"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "proposalId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "resolve_accessproposals",
+ "description": "Approves or denies an access proposal. For more information, see Manage pending access proposals.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "Required. The ID of the item the request is on.",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "proposalId": {
+ "type": "string",
+ "description": "Required. The ID of the access proposal to resolve.",
+ "minLength": 1,
+ "examples": [
+ "01JBQM3K8TGHZX9RNVQM5Y2PAZ",
+ "01JBQM3K8TGHZX9RNVQM5Y2PB0"
+ ]
+ },
+ "action": {
+ "type": "string",
+ "description": "Required. The action to take on the access proposal.",
+ "enum": [
+ "ACTION_UNSPECIFIED",
+ "ACCEPT",
+ "DENY"
+ ],
+ "examples": [
+ "ACCEPT",
+ "DENY"
+ ]
+ },
+ "role": {
+ "type": "array",
+ "description": "Optional. The roles that the approver has allowed, if any. Note: This field is required for the ACCEPT action.",
+ "items": {
+ "type": "string"
+ },
+ "examples": [
+ [
+ "reader"
+ ],
+ [
+ "writer"
+ ],
+ [
+ "commenter"
+ ]
+ ]
+ },
+ "view": {
+ "type": "string",
+ "description": "Optional. Indicates the view for this access proposal. This should only be set when the proposal belongs to a view. Only 'published' is supported.",
+ "examples": [
+ "published"
+ ]
+ },
+ "sendNotification": {
+ "type": "boolean",
+ "description": "Optional. Whether to send an email to the requester when the access proposal is denied or accepted.",
+ "default": true
+ }
+ },
+ "required": [
+ "fileId",
+ "proposalId",
+ "action"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_accessproposals",
+ "description": "List the access proposals on a file. For more information, see Manage pending access proposals. Note: Only approvers are able to list access proposals on a file. If the user isn't an approver, a 403 error is returned.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "Required. The ID of the item the request is on.",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Optional. The continuation token on the list of access requests.",
+ "examples": [
+ "0",
+ "100",
+ "200"
+ ]
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "Optional. The number of results per page.",
+ "minimum": 1,
+ "maximum": 100,
+ "default": 100,
+ "examples": [
+ 10,
+ 25,
+ 50,
+ 100
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_teamdrive",
+ "description": "Deprecated: Use drives.update instead. Updates a Team Drive's metadata. This method supports patch semantics.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "team_drive_id": {
+ "type": "string",
+ "description": "The ID of the Team Drive",
+ "minLength": 1,
+ "examples": [
+ "0AOp1234567890abcdef",
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of this Team Drive.",
+ "minLength": 1,
+ "examples": [
+ "My Team Drive",
+ "Engineering Projects"
+ ]
+ },
+ "color_rgb": {
+ "type": "string",
+ "description": "The color of this Team Drive as an RGB hex string. It can only be set on a drive.teamdrives.update request that does not set theme_id.",
+ "pattern": "^#[0-9A-Fa-f]{6}$",
+ "examples": [
+ "#FF0000",
+ "#00FF00",
+ "#0000FF"
+ ]
+ },
+ "theme_id": {
+ "type": "string",
+ "description": "The ID of the theme from which the background image and color will be set. The set of possible teamDriveThemes can be retrieved from a drive.about.get response. When not specified on a drive.teamdrives.create request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set color_rgb or background_image_file.",
+ "examples": [
+ "theme_1",
+ "theme_2"
+ ]
+ },
+ "background_image_file": {
+ "type": "object",
+ "description": "An image file and cropping parameters from which a background image for this Team Drive is set. This is a write only field; it can only be set on drive.teamdrives.update requests that don't set theme_id. When specified, all fields of the background_image_file must be set.",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of an image file in Drive to use for the background image.",
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ]
+ },
+ "x_coordinate": {
+ "type": "number",
+ "description": "The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.1,
+ 0.5,
+ 0.9
+ ]
+ },
+ "y_coordinate": {
+ "type": "number",
+ "description": "The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.1,
+ 0.5,
+ 0.9
+ ]
+ },
+ "width": {
+ "type": "number",
+ "description": "The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image.",
+ "minimum": 0,
+ "maximum": 1,
+ "examples": [
+ 0.5,
+ 0.8,
+ 1.0
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "x_coordinate",
+ "y_coordinate",
+ "width"
+ ]
+ },
+ "use_domain_admin_access": {
+ "type": "boolean",
+ "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the Team Drive belongs.",
+ "default": false
+ }
+ },
+ "required": [
+ "team_drive_id"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_revisions",
+ "description": "Lists a file's revisions in Google Drive. Retrieves all versions and revision history of a file with support for pagination. Essential for version control, reviewing changes, and accessing previous versions of documents.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to list revisions for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of revisions to return per page (optional, default: 10, max: 1000)",
+ "minimum": 1,
+ "maximum": 1000,
+ "default": 10,
+ "examples": [
+ 10,
+ 25,
+ 50,
+ 100
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response (optional)",
+ "examples": [
+ "CAISBggBEAEYAg",
+ "CAISBggBEAIYAw",
+ "nextPageToken123"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_revisions",
+ "description": "Retrieves a specific revision by ID for a file in Google Drive. Returns complete revision metadata including version history, publish settings, and export links. Essential for accessing specific versions of documents.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the revision (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "revisionId": {
+ "type": "string",
+ "description": "The ID of the revision to retrieve (required)",
+ "minLength": 1,
+ "examples": [
+ "01JBQM3K8TGHZX9RNVQM5Y2P8V",
+ "01JBQM3K8TGHZX9RNVQM5Y2P8W",
+ "revision_123"
+ ]
+ },
+ "acknowledgeAbuse": {
+ "type": "boolean",
+ "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. Only applicable when downloading file content and user is owner or shared drive organizer.",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "revisionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_revisions",
+ "description": "Deletes a specific revision of a file in Google Drive. Uses soft deletion to maintain revision history integrity. Only non-published revisions can be deleted unless specifically overridden.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the revision (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "revisionId": {
+ "type": "string",
+ "description": "The ID of the revision to delete (required)",
+ "minLength": 1,
+ "examples": [
+ "01JBQM3K8TGHZX9RNVQM5Y2P8V",
+ "01JBQM3K8TGHZX9RNVQM5Y2P8W",
+ "revision_123"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "revisionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_teamdrives",
+ "description": "Creates a new shared drive (Team Drive) in Google Drive. Requires a unique requestId for idempotency.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "requestId": {
+ "type": "string",
+ "description": "Unique ID for this request (e.g., UUID). Required for idempotency."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the shared drive."
+ },
+ "colorRgb": {
+ "type": "string",
+ "description": "Optional hex color."
+ },
+ "themeId": {
+ "type": "string",
+ "description": "Optional theme ID."
+ },
+ "backgroundImageLink": {
+ "type": "string",
+ "description": "Optional background image link."
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "Whether the drive is hidden."
+ }
+ },
+ "required": [
+ "requestId",
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_teamdrives",
+ "description": "Deletes a shared drive (Team Drive) permanently in Google Drive. Requires organizer or admin permissions.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamDriveId": {
+ "type": "string",
+ "description": "The ID of the shared drive to delete",
+ "examples": [
+ "drive_1",
+ "drive_abc123"
+ ]
+ }
+ },
+ "required": [
+ "teamDriveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_teamdrives",
+ "description": "Retrieves metadata for a shared drive (Team Drive) by ID in Google Drive. Requires organizer or member access to the drive.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamDriveId": {
+ "type": "string",
+ "description": "The ID of the shared drive to retrieve",
+ "examples": [
+ "drive_1",
+ "drive_abc123"
+ ]
+ }
+ },
+ "required": [
+ "teamDriveId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_teamdrives",
+ "description": "Lists shared drives (Team Drives) accessible to the authenticated user. Supports optional pagination and query filters.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "pageSize": {
+ "type": "integer",
+ "description": "Maximum number of shared drives to return",
+ "default": 10,
+ "examples": [
+ 5,
+ 10,
+ 20
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Token for retrieving the next page of results"
+ },
+ "q": {
+ "type": "string",
+ "description": "Query string to filter shared drives by name",
+ "examples": [
+ "Team",
+ "Marketing"
+ ]
+ }
+ },
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "stop_channels",
+ "description": "Stops a notification channel used to watch for changes to a file or folder. Essential for managing push notifications and cleaning up webhook subscriptions in Google Drive. Use this to stop receiving notifications when you no longer need to monitor changes to specific resources.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The UUID or other unique ID of the notification channel being stopped (required)",
+ "minLength": 1,
+ "examples": [
+ "4ba78bf0-6a47-11e2-bcfd-0800200c9a66",
+ "01JCQM3K8TGHZX9RNVQM5Y2PAZ",
+ "channel_12345_abcdef"
+ ]
+ },
+ "resourceId": {
+ "type": "string",
+ "description": "An opaque ID that identifies the resource being watched on this channel (required). This is returned when the channel was created.",
+ "minLength": 1,
+ "examples": [
+ "ret08u3rv24htgh289g",
+ "o-bm5gp5JtLykQGJGuQq5fKkqBLRXBxLRpfaKD_Hg6Vs",
+ "resource_98765_zyxwvu"
+ ]
+ },
+ "token": {
+ "type": "string",
+ "description": "An arbitrary string delivered to the target address with each notification (optional). Used for verification purposes.",
+ "examples": [
+ "my-secret-token",
+ "webhook-verification-123",
+ "user-defined-token"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "resourceId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_files",
+ "description": "Gets a file's metadata or content by ID. To get a file, use the get method on the files resource with the fileId path parameter. The method returns the file as an instance of a files resource. If you provide the URL parameter alt=media, then the response includes the file contents in the response body. Downloading content with alt=media only works if the file is stored in Drive. Essential for retrieving file information, downloading file content, accessing file metadata, and understanding file properties and permissions.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file (required). This is the unique identifier for the file in Google Drive.",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s",
+ "1abc123def456ghi789jkl012mno345pqr678stu901vwx"
+ ]
+ },
+ "acknowledgeAbuse": {
+ "type": "boolean",
+ "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the alt parameter is set to media and the user is the owner of the file or an organizer of the shared drive in which the file resides (optional, default: false)"
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: true)"
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported (optional)"
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response (optional)",
+ "examples": [
+ "label_1,label_2,label_3",
+ "important,draft,review"
+ ]
+ },
+ "alt": {
+ "type": "string",
+ "description": "Specifies the format that the API should return for the file. Use 'media' to download file content (optional)",
+ "examples": [
+ "media"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_files",
+ "description": "Lists the user's files with comprehensive filtering, pagination, and search capabilities. Supports filtering by corpora (user, domain, drive, allDrives), search queries, ordering, and pagination. Essential for retrieving file listings, searching files, implementing file browsers, and managing file collections. Use this to get file lists, search for specific files, browse user's Drive contents, or implement paginated file navigation.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "corpora": {
+ "type": "string",
+ "description": "Bodies of items (files or documents) to which the query applies. Supported values: 'user', 'domain', 'drive', 'allDrives'. Default: 'user'",
+ "examples": [
+ "user",
+ "domain",
+ "drive",
+ "allDrives"
+ ]
+ },
+ "driveId": {
+ "type": "string",
+ "description": "ID of the shared drive to search (optional)",
+ "examples": [
+ "0AOp1234567890abcdef",
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ]
+ },
+ "includeItemsFromAllDrives": {
+ "type": "boolean",
+ "description": "Whether both My Drive and shared drive items should be included in results (optional, default: false)"
+ },
+ "orderBy": {
+ "type": "string",
+ "description": "A comma-separated list of sort keys. Valid keys: 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', 'name', 'name_natural', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', 'viewedByMeTime'. Add 'desc' for descending order (optional)",
+ "examples": [
+ "modifiedTime desc,name",
+ "createdTime",
+ "name asc",
+ "starred desc,viewedByMeTime"
+ ]
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of files to return per page (optional, default: 100, max: 1000)",
+ "minimum": 1,
+ "maximum": 1000,
+ "examples": [
+ 10,
+ 50,
+ 100,
+ 200
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page (optional)",
+ "examples": [
+ "100",
+ "200",
+ "300"
+ ]
+ },
+ "q": {
+ "type": "string",
+ "description": "A query for filtering the file results. Supports searching by file name, MIME type, and properties (optional)",
+ "examples": [
+ "name contains 'document'",
+ "mimeType = 'application/pdf'",
+ "starred = true",
+ "trashed = false",
+ "modifiedTime > '2024-01-01T00:00:00Z'"
+ ]
+ },
+ "spaces": {
+ "type": "string",
+ "description": "A comma-separated list of spaces to query within the corpora. Supported values: 'drive', 'appDataFolder' (optional, default: 'drive,appDataFolder')",
+ "examples": [
+ "drive",
+ "appDataFolder",
+ "drive,appDataFolder"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: true)"
+ },
+ "trashed": {
+ "type": "boolean",
+ "description": "Whether to include trashed files in the results. If not specified, includes both trashed and non-trashed files (optional)",
+ "examples": [
+ true,
+ false
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_files",
+ "description": "Updates a file's metadata, content, or both. When calling this method, only populate fields in the request that you want to modify. When updating fields, some fields might be changed automatically, such as modifiedDate. This method supports patch semantics. Essential for modifying file properties, updating file names, changing file descriptions, managing file organization, and updating custom metadata. Use this to rename files, update descriptions, star/unstar files, move files between folders, or update custom properties.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to update (required). This is the unique identifier for the file in Google Drive.",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s",
+ "1abc123def456ghi789jkl012mno345pqr678stu901vwx"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the file (optional)",
+ "examples": [
+ "Updated Document Name",
+ "My New File"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description of the file (optional)",
+ "examples": [
+ "Updated description",
+ "This is my updated file"
+ ]
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the file (optional)",
+ "examples": [
+ "application/vnd.google-apps.document",
+ "application/pdf",
+ "text/plain"
+ ]
+ },
+ "starred": {
+ "type": "boolean",
+ "description": "Whether the user has starred the file (optional)",
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "trashed": {
+ "type": "boolean",
+ "description": "Whether the file has been trashed (optional)",
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "properties": {
+ "type": "object",
+ "description": "A collection of arbitrary key-value pairs which are private to the requesting app (optional)",
+ "examples": [
+ {
+ "custom_field": "custom_value",
+ "priority": "high"
+ },
+ {
+ "department": "engineering",
+ "status": "active"
+ }
+ ]
+ },
+ "appProperties": {
+ "type": "object",
+ "description": "A collection of arbitrary key-value pairs which are visible to all apps (optional)",
+ "examples": [
+ {
+ "app_version": "1.0",
+ "last_sync": "2024-01-16T10:00:00Z"
+ },
+ {
+ "category": "work",
+ "tags": [
+ "important",
+ "draft"
+ ]
+ }
+ ]
+ },
+ "addParents": {
+ "type": "string",
+ "description": "A comma-separated list of parent IDs to add (optional)",
+ "examples": [
+ "parent_folder_1",
+ "parent_folder_1,parent_folder_2"
+ ]
+ },
+ "removeParents": {
+ "type": "string",
+ "description": "A comma-separated list of parent IDs to remove (optional)",
+ "examples": [
+ "old_parent_1",
+ "old_parent_1,old_parent_2"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional, default: true)"
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported (optional)"
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response (optional)",
+ "examples": [
+ "label_1,label_2",
+ "important,draft,review"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_files_labels",
+ "description": "Lists the labels on a file. To list the file labels, use the files.listLabels method. The request body must be empty. The method also takes the optional query parameter maxResults to set the maximum number of labels to return per page. If not set, 100 results are returned. Essential for retrieving file label information, understanding file categorization, and managing file metadata through labels.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to list labels for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s",
+ "1abc123def456ghi789jkl012mno345pqr678stu901vwx"
+ ]
+ },
+ "maxResults": {
+ "type": "integer",
+ "description": "The maximum number of labels to return per page (optional, default: 100, max: 1000)",
+ "minimum": 1,
+ "maximum": 1000,
+ "examples": [
+ 50,
+ 100,
+ 200
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page (optional)",
+ "examples": [
+ "100",
+ "200",
+ "300"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "modify_files_labels",
+ "description": "Modifies the set of labels applied to a file using Google Drive API specification. For more information, see Set a label field on a file. Returns a list of the labels that were added or modified. Essential for updating file categorization, managing file metadata, and organizing files through labels. Use this to add new labels to files, update existing label values, or remove labels from files.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to modify labels for (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s",
+ "1abc123def456ghi789jkl012mno345pqr678stu901vwx"
+ ]
+ },
+ "labelModifications": {
+ "type": "array",
+ "description": "The list of label modifications to apply (required)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "labelId": {
+ "type": "string",
+ "description": "The ID of the label to modify"
+ },
+ "fieldModifications": {
+ "type": "array",
+ "description": "The list of modifications to this label's fields",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fieldId": {
+ "type": "string",
+ "description": "The ID of the field to be modified"
+ },
+ "setDateValues": {
+ "type": "array",
+ "description": "Replaces the value of a date field with these new values. The string must be in the RFC 3339 full-date format: YYYY-MM-DD",
+ "items": {
+ "type": "string"
+ }
+ },
+ "setTextValues": {
+ "type": "array",
+ "description": "Sets the value of a text field",
+ "items": {
+ "type": "string"
+ }
+ },
+ "setSelectionValues": {
+ "type": "array",
+ "description": "Replaces a selection field with these new values",
+ "items": {
+ "type": "string"
+ }
+ },
+ "setIntegerValues": {
+ "type": "array",
+ "description": "Replaces the value of an integer field with these new values",
+ "items": {
+ "type": "string"
+ }
+ },
+ "setUserValues": {
+ "type": "array",
+ "description": "Replaces a user field with these new values. The values must be a valid email addresses",
+ "items": {
+ "type": "string"
+ }
+ },
+ "unsetValues": {
+ "type": "boolean",
+ "description": "Unsets the values for this field"
+ },
+ "kind": {
+ "type": "string",
+ "description": "This is always 'drive#labelFieldModification'",
+ "default": "drive#labelFieldModification"
+ }
+ },
+ "required": [
+ "fieldId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "removeLabel": {
+ "type": "boolean",
+ "description": "If true, the label will be removed from the file"
+ },
+ "kind": {
+ "type": "string",
+ "description": "This is always 'drive#labelModification'",
+ "default": "drive#labelModification"
+ }
+ },
+ "required": [
+ "labelId"
+ ],
+ "additionalProperties": false
+ },
+ "examples": [
+ [
+ {
+ "labelId": "label_123",
+ "fieldModifications": [
+ {
+ "fieldId": "field_456",
+ "setTextValues": [
+ "high priority"
+ ],
+ "kind": "drive#labelFieldModification"
+ }
+ ],
+ "kind": "drive#labelModification"
+ },
+ {
+ "labelId": "label_789",
+ "removeLabel": true,
+ "kind": "drive#labelModification"
+ }
+ ]
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "labelModifications"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_file",
+ "description": "Creates a new file in Google Drive (metadata-only version, no binary upload).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "ignoreDefaultVisibility": {
+ "type": "boolean",
+ "description": "Ignore the domain's default visibility for the file.",
+ "default": false
+ },
+ "keepRevisionForever": {
+ "type": "boolean",
+ "description": "Whether to set the keepForever field in the new head revision.",
+ "default": false
+ },
+ "ocrLanguage": {
+ "type": "string",
+ "description": "Hint for OCR language (ISO 639-1 code)"
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the request supports both My Drives and shared drives"
+ },
+ "uploadType": {
+ "type": "string",
+ "enum": [
+ "media",
+ "multipart",
+ "resumable"
+ ],
+ "description": "The type of upload request to the /upload URI.",
+ "default": "media"
+ },
+ "useContentAsIndexableText": {
+ "type": "boolean",
+ "description": "Whether to use the uploaded content as indexable text"
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported"
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response"
+ },
+ "parents": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The ID of the parent folder containing the file. A file can only have one parent folder; specifying multiple parents isn't supported."
+ },
+ "permissions": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ },
+ "description": "The permissions to set for the file."
+ },
+ "properties": {
+ "type": "object",
+ "description": "A collection of arbitrary key-value pairs which are private to the requesting app"
+ },
+ "appProperties": {
+ "type": "object",
+ "description": "A collection of arbitrary key-value pairs which are visible to all apps"
+ },
+ "permissionIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The IDs of the permissions to set for the file."
+ },
+ "contentRestrictions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "readOnly": {
+ "type": "boolean",
+ "description": "Whether the content of the file is read-only."
+ },
+ "reason": {
+ "type": "string",
+ "description": "The reason for the content restriction."
+ },
+ "ownerRestricted": {
+ "type": "boolean",
+ "description": "Whether the content of the file is restricted to the owner."
+ },
+ "systemRestricted": {
+ "type": "boolean",
+ "description": "Whether the content of the file is restricted to the system."
+ }
+ }
+ },
+ "description": "Content restriction details"
+ },
+ "copyRequiresWriterPermission": {
+ "type": "boolean",
+ "description": "Whether the options to copy, print, or download this file, should be disabled for readers and commenters"
+ },
+ "contentHints": {
+ "type": "object",
+ "properties": {
+ "indexableText": {
+ "type": "string",
+ "description": "Text to be indexed for the file to improve fullText queries"
+ },
+ "thumbnail": {
+ "type": "object",
+ "description": "Thumbnail image and metadata"
+ }
+ },
+ "description": "Content hints for the file"
+ },
+ "writersCanShare": {
+ "type": "boolean",
+ "description": "Whether writers can share the document with other users"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the file",
+ "examples": [
+ "text/plain",
+ "image/jpeg",
+ "application/pdf"
+ ]
+ },
+ "folderColorRgb": {
+ "type": "string",
+ "description": "The color for a folder or a shortcut to a folder"
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the file",
+ "examples": [
+ "document.txt",
+ "photo.jpg"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "A short description of the file"
+ },
+ "starred": {
+ "type": "boolean",
+ "description": "Whether the user has starred the file"
+ },
+ "trashed": {
+ "type": "boolean",
+ "description": "Whether the file has been trashed"
+ },
+ "createdTime": {
+ "type": "string",
+ "description": "The time at which the file was created"
+ },
+ "modifiedTime": {
+ "type": "string",
+ "description": "The last time the file was modified by anyone"
+ },
+ "originalFilename": {
+ "type": "string",
+ "description": "The original filename of the uploaded file"
+ },
+ "shortcutDetails": {
+ "type": "object",
+ "properties": {
+ "targetId": {
+ "type": "string",
+ "description": "The ID of the file that this shortcut points to"
+ }
+ },
+ "description": "Shortcut file details"
+ },
+ "inheritedPermissionsDisabled": {
+ "type": "boolean",
+ "description": "Whether the permissions of this file are inherited from a parent folder"
+ },
+ "downloadRestrictions": {
+ "type": "object",
+ "properties": {
+ "restricted": {
+ "type": "boolean",
+ "description": "Whether the file is restricted from download"
+ },
+ "reason": {
+ "type": "string",
+ "description": "The reason for the download restriction"
+ }
+ },
+ "description": "Download restrictions metadata"
+ }
+ },
+ "required": [
+ "name",
+ "mimeType"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_files",
+ "description": "Permanently deletes a file owned by the user in Google Drive.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to delete",
+ "examples": [
+ "file_1",
+ "file_abc123"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "empty_files_trash",
+ "description": "Permanently empties the user's trash in Google Drive. Deletes all trashed files owned by the user.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "Optional Drive ID. If set, empties the trash of the specified shared drive.",
+ "examples": [
+ "drive_1"
+ ]
+ }
+ },
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "export_files",
+ "description": "Exports a Google Workspace file to the requested MIME type.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to export",
+ "examples": [
+ "file_1",
+ "file_abc123"
+ ]
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type to export the file as",
+ "examples": [
+ "application/pdf",
+ "text/plain"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "mimeType"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "generate_files_Ids",
+ "description": "Generates a set of file IDs that can be provided in create or copy requests.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "count": {
+ "type": "integer",
+ "description": "Number of IDs to generate",
+ "default": 10
+ },
+ "space": {
+ "type": "string",
+ "description": "Space (drive or appDataFolder)",
+ "default": "drive"
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of items (files or shortcuts)",
+ "default": "files"
+ }
+ },
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "create_replies",
+ "description": "Creates a reply to a comment on a Google Drive file. Adds a response to an existing comment thread, enabling collaborative discussions and feedback workflows. Essential for comment-based collaboration and file review processes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment to reply to (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "content": {
+ "type": "string",
+ "description": "The plain text content of the reply (required)",
+ "minLength": 1,
+ "maxLength": 8192,
+ "examples": [
+ "Thanks for the feedback!",
+ "I'll look into this issue.",
+ "Great suggestion, I'll implement this."
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId",
+ "content"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "delete_replies",
+ "description": "Deletes a reply to a comment on a Google Drive file. Removes a reply from a comment thread, useful for cleaning up conversations or removing inappropriate content. Essential for comment moderation and cleanup workflows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment containing the reply (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "replyId": {
+ "type": "string",
+ "description": "The ID of the reply to delete (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId",
+ "replyId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_replies",
+ "description": "Gets a specific reply to a comment on a Google Drive file. Retrieves detailed information about a single reply, including content, author, timestamps, and metadata. Essential for viewing reply details and building comment interfaces.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment containing the reply (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "replyId": {
+ "type": "string",
+ "description": "The ID of the reply to retrieve (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "includeDeleted": {
+ "type": "boolean",
+ "description": "Whether to return deleted replies. Deleted replies will not include their original content.",
+ "default": false
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId",
+ "replyId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_replies",
+ "description": "Lists all replies to a comment on a Google Drive file. Retrieves a paginated list of replies with their content, authors, timestamps, and metadata. Essential for viewing all replies in a comment thread and building comprehensive comment interfaces.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment to list replies for (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "includeDeleted": {
+ "type": "boolean",
+ "description": "Whether to include deleted replies in the response (optional, default: false). Deleted replies will not include their original content.",
+ "default": false
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of replies to return per page (optional, default: 10, max: 1000)",
+ "minimum": 1,
+ "maximum": 1000,
+ "default": 10,
+ "examples": [
+ 10,
+ 25,
+ 50,
+ 100
+ ]
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response (optional)",
+ "examples": [
+ "CAISBggBEAEYAg",
+ "CAISBggBEAIYAw",
+ "nextPageToken123"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_replies",
+ "description": "Updates a reply to a comment on a Google Drive file with patch semantics. Modifies the content of an existing reply, enabling users to edit their responses in comment threads. Essential for comment correction, clarification, and collaborative editing workflows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the comment (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "commentId": {
+ "type": "string",
+ "description": "The ID of the comment containing the reply (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "replyId": {
+ "type": "string",
+ "description": "The ID of the reply to update (required)",
+ "minLength": 1,
+ "examples": [
+ "AAAABg8o8Zk",
+ "AAAACgpKm2k"
+ ]
+ },
+ "content": {
+ "type": "string",
+ "description": "The updated plain text content of the reply (required)",
+ "minLength": 1,
+ "maxLength": 8192,
+ "examples": [
+ "Thank you for the clarification!",
+ "I've updated my response based on your feedback.",
+ "Let me correct that information..."
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "commentId",
+ "replyId",
+ "content"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "watch_files",
+ "description": "Subscribes to changes to a file in Google Drive. Creates a notification channel that will receive updates when the file is modified, enabling real-time monitoring and synchronization. Essential for building responsive applications that need to react to file changes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to watch (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives (optional)",
+ "default": false,
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "acknowledgeAbuse": {
+ "type": "boolean",
+ "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the alt parameter is set to media and the user is the owner of the file or an organizer of the shared drive in which the file resides (optional)",
+ "default": false,
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only published is supported (optional)",
+ "examples": [
+ "published"
+ ]
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response (optional)",
+ "examples": [
+ "label1,label2,label3"
+ ]
+ },
+ "id": {
+ "type": "string",
+ "description": "A UUID or similar unique string that identifies this channel (optional)",
+ "examples": [
+ "channel-123",
+ "watch-subscription-456"
+ ]
+ },
+ "token": {
+ "type": "string",
+ "description": "An arbitrary string delivered to the target address with each notification (optional)",
+ "examples": [
+ "notification-token-123",
+ "webhook-secret-456"
+ ]
+ },
+ "expiration": {
+ "type": "string",
+ "description": "Date and time of notification channel expiration (optional)",
+ "examples": [
+ "2024-12-31T23:59:59Z",
+ "2025-01-15T12:00:00Z"
+ ]
+ },
+ "address": {
+ "type": "string",
+ "description": "The address where notifications are delivered for this channel (optional)",
+ "examples": [
+ "https://example.com/notifications",
+ "https://myapp.com/webhook"
+ ]
+ },
+ "payload": {
+ "type": "boolean",
+ "description": "Whether payload is included in notifications (optional)",
+ "default": false
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of delivery mechanism used for this channel (optional)",
+ "default": "web_hook",
+ "examples": [
+ "web_hook",
+ "webhook"
+ ]
+ },
+ "params": {
+ "type": "object",
+ "description": "Additional parameters controlling delivery channel behavior (optional)",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "examples": [
+ {
+ "name": "wrench",
+ "mass": "1.3kg",
+ "count": "3"
+ }
+ ]
+ },
+ "kind": {
+ "type": "string",
+ "description": "Identifies this as a notification channel used to watch for changes to a resource (optional)",
+ "default": "api#channel",
+ "examples": [
+ "api#channel"
+ ]
+ },
+ "resourceId": {
+ "type": "string",
+ "description": "An opaque ID that identifies the resource being watched on this channel. Stable across different API versions (optional)",
+ "examples": [
+ "file_123_channel_456",
+ "resource_789"
+ ]
+ },
+ "resourceUri": {
+ "type": "string",
+ "description": "A version-specific identifier for the watched resource (optional)",
+ "examples": [
+ "https://www.googleapis.com/drive/v3/files/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "https://www.googleapis.com/drive/v3/files/1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ }
+ },
+ "required": [
+ "fileId",
+ "id",
+ "resourceId",
+ "resourceUri",
+ "address"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "download_files",
+ "description": "Downloads the content of a file from Google Drive. Creates a download operation that can be used to retrieve file content in various formats. Essential for accessing file data, exporting documents, and downloading media files. Operations are valid for 24 hours from creation.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file to download (required)",
+ "minLength": 1,
+ "examples": [
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1mGSuea-bkBcvWaakJdZnjGpVN3rUw1cBG7XWLXj9M8s"
+ ]
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type the file should be downloaded as (optional)",
+ "examples": [
+ "application/pdf",
+ "text/plain",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+ ]
+ },
+ "revisionId": {
+ "type": "string",
+ "description": "The revision ID of the file to download (optional)",
+ "examples": [
+ "0BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
+ "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
+ ]
+ }
+ },
+ "required": [
+ "fileId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_about",
+ "description": "Gets information about the user, the user's Drive, and system capabilities. Essential for retrieving user profile information, storage quota details, drive information, and system capabilities. Use this to get user details, check storage usage, list available drives, and understand system limits and capabilities. Supports Google Drive API fields parameter syntax including nested fields with parentheses.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fields": {
+ "type": "string",
+ "description": "The fields parameter specifies which fields to include in the response. Use * for all fields, specific field names, or nested syntax like storageQuota(limit,usage). If not specified, returns default fields (kind,user,storageQuota).",
+ "examples": [
+ "*",
+ "kind",
+ "user",
+ "storageQuota",
+ "storageQuota(limit,usage)",
+ "user.displayName,user.emailAddress",
+ "kind,user,storageQuota"
+ ]
+ }
+ },
+ "required": [],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "get_app",
+ "description": "Gets a specific app by ID. Essential for retrieving detailed information about installed Google Drive apps, including their capabilities, supported file types, URLs, and metadata. Use this to get app details, check app capabilities, retrieve app configuration, or understand what apps are available for file operations.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "appId": {
+ "type": "string",
+ "description": "The ID of the app to retrieve (required). This is the unique identifier for the app in Google Drive.",
+ "minLength": 1,
+ "examples": [
+ "felcaaldnbdncclmgdcncolpebgiejap",
+ "aohghmighlieiainnegkcijnfilokake",
+ "nmmhkkegccagdldgiimedpiccmgmieda",
+ "google_docs_app_id"
+ ]
+ }
+ },
+ "required": [
+ "appId"
+ ]
+ }
+ },
+ {
+ "name": "list_apps",
+ "description": "Lists a user's installed apps with optional filtering. Essential for retrieving all installed Google Drive apps, filtering by file extensions or MIME types, and understanding available apps for file operations. Use this to get app listings, find apps that support specific file types, or discover available apps for document creation and editing.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "appFilterExtensions": {
+ "type": "string",
+ "description": "A comma-separated list of file extensions to limit returned results. Apps that can open any of the given file extensions are included in the response.",
+ "examples": [
+ "docx,pptx",
+ ".xlsx,.csv",
+ ".pdf,.doc",
+ "txt,md"
+ ]
+ },
+ "appFilterMimeTypes": {
+ "type": "string",
+ "description": "A comma-separated list of MIME types to limit returned results. Apps that can open any of the given MIME types are included in the response.",
+ "examples": [
+ "application/vnd.google-apps.form,application/vnd.google-apps.site",
+ "application/vnd.google-apps.document,application/vnd.google-apps.spreadsheet",
+ "application/pdf,text/plain",
+ "image/jpeg,image/png"
+ ]
+ },
+ "languageCode": {
+ "type": "string",
+ "description": "A language or locale code, as defined by BCP 47, with some extensions from Unicode's LDML format.",
+ "examples": [
+ "en-us",
+ "fr-ca",
+ "es-es",
+ "de-de"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "get_changes_start_page_token",
+ "description": "Gets the starting pageToken for listing future changes. Essential for change tracking and synchronization in Google Drive. Use this to get a page token that can be used to list changes from a specific point in time, enabling incremental sync and change monitoring across drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive for which the starting pageToken for listing future changes from that shared drive will be returned. If not provided, returns token for all drives (global scope).",
+ "examples": [
+ "drive_123",
+ "shared_drive_456",
+ "team_drive_789"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives. Set to true if your application can handle both personal and shared drives.",
+ "default": false
+ },
+ "supportsTeamDrives": {
+ "type": "boolean",
+ "description": "Deprecated: Use supportsAllDrives instead. This parameter is kept for backward compatibility."
+ },
+ "teamDriveId": {
+ "type": "string",
+ "description": "Deprecated: Use driveId instead. This parameter is kept for backward compatibility.",
+ "examples": [
+ "team_drive_123",
+ "shared_drive_456"
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "list_changes",
+ "description": "Lists the changes for a user or shared drive. Essential for change tracking, synchronization, and monitoring file modifications in Google Drive. Use this to retrieve paginated lists of changes, track file modifications, implement incremental sync, or monitor drive activity with comprehensive filtering options.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "pageToken": {
+ "type": "string",
+ "description": "The token for continuing a previous list request on the next page (required). This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.",
+ "minLength": 1,
+ "examples": [
+ "token_1234567890abcdef",
+ "next_token_abc123def456",
+ "start_token_xyz789"
+ ]
+ },
+ "driveId": {
+ "type": "string",
+ "description": "The shared drive from which changes will be returned. If specified the change IDs will be reflective of the shared drive.",
+ "examples": [
+ "drive_123",
+ "shared_drive_456",
+ "team_drive_789"
+ ]
+ },
+ "includeCorpusRemovals": {
+ "type": "boolean",
+ "description": "Whether changes should include the file resource if the file is still accessible by the user at the time of the request, even when a file was removed from the list of changes.",
+ "default": false
+ },
+ "includeItemsFromAllDrives": {
+ "type": "boolean",
+ "description": "Whether both My Drive and shared drive items should be included in results.",
+ "default": false
+ },
+ "includeRemoved": {
+ "type": "boolean",
+ "description": "Whether to include changes indicating that items have been removed from the list of changes, for example by deletion or loss of access.",
+ "default": false
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The maximum number of changes to return per page (1-1000).",
+ "minimum": 1,
+ "maximum": 1000,
+ "default": 100,
+ "examples": [
+ 10,
+ 50,
+ 100,
+ 500
+ ]
+ },
+ "restrictToMyDrive": {
+ "type": "boolean",
+ "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.",
+ "default": false
+ },
+ "spaces": {
+ "type": "string",
+ "description": "A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.",
+ "examples": [
+ "drive",
+ "appDataFolder",
+ "drive,appDataFolder"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives.",
+ "default": false
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.",
+ "examples": [
+ "published"
+ ]
+ },
+ "includeLabels": {
+ "type": "string",
+ "description": "A comma-separated list of IDs of labels to include in the labelInfo part of the response.",
+ "examples": [
+ "label_123",
+ "label_123,label_456"
+ ]
+ }
+ },
+ "required": [
+ "pageToken"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "update_revisions",
+ "description": "Updates a file revision in Google Drive with patch semantics. Allows setting keepForever, published, publishAuto and related revision metadata.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "fileId": {
+ "type": "string",
+ "description": "The ID of the file containing the revision",
+ "examples": [
+ "file_1"
+ ]
+ },
+ "revisionId": {
+ "type": "string",
+ "description": "The ID of the revision to update",
+ "examples": [
+ "rev_1"
+ ]
+ },
+ "keepForever": {
+ "type": "boolean",
+ "description": "Whether to keep this revision forever"
+ },
+ "published": {
+ "type": "boolean",
+ "description": "Whether this revision is published (for Docs, Sheets, Slides)"
+ },
+ "publishAuto": {
+ "type": "boolean",
+ "description": "Whether subsequent revisions should be automatically published"
+ }
+ },
+ "required": [
+ "fileId",
+ "revisionId"
+ ],
+ "additionalProperties": false
+ }
+ },
+ {
+ "name": "watch_changes",
+ "description": "Sets up a notification channel to watch for changes to Google Drive resources. Creates a webhook subscription that sends notifications when files are created, modified, deleted, or shared. Essential for real-time synchronization and change monitoring across drives and shared drives.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "pageToken": {
+ "type": "string",
+ "description": "The page token for listing changes. Use the token from get_changes_start_page_token to watch for future changes. Each page token is valid for a limited time.",
+ "minLength": 1,
+ "examples": [
+ "changes_token_abc123",
+ "page_token_def456",
+ "start_token_789xyz"
+ ]
+ },
+ "driveId": {
+ "type": "string",
+ "description": "The ID of the shared drive for which changes will be watched. If not provided, watches changes across all drives accessible to the user.",
+ "examples": [
+ "drive_123",
+ "shared_drive_456",
+ "team_drive_789"
+ ]
+ },
+ "includeCorpusRemovals": {
+ "type": "boolean",
+ "description": "Whether to include changes outside the target corpus in the result.",
+ "default": false
+ },
+ "includeItemsFromAllDrives": {
+ "type": "boolean",
+ "description": "Whether both My Drive and shared drive items should be included in results.",
+ "default": true
+ },
+ "includePermissionsForView": {
+ "type": "string",
+ "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.",
+ "examples": [
+ "published"
+ ]
+ },
+ "includeRemoved": {
+ "type": "boolean",
+ "description": "Whether to include removed items (trashed/deleted files) in the response to detect file deletions.",
+ "default": true
+ },
+ "restrictToMyDrive": {
+ "type": "boolean",
+ "description": "Whether to restrict the results to changes inside the My Drive hierarchy.",
+ "default": false
+ },
+ "spaces": {
+ "type": "string",
+ "description": "A comma-separated list of spaces to query within the corpus. Supported values are 'drive' and 'appDataFolder'.",
+ "default": "drive",
+ "examples": [
+ "drive",
+ "drive,appDataFolder"
+ ]
+ },
+ "supportsAllDrives": {
+ "type": "boolean",
+ "description": "Whether the requesting application supports both My Drives and shared drives.",
+ "default": true
+ },
+ "id": {
+ "type": "string",
+ "description": "A unique identifier for the notification channel. Must be a UUID-like string to ensure uniqueness across all channels.",
+ "minLength": 1,
+ "examples": [
+ "channel_abc123def456",
+ "notification_789xyz012",
+ "webhook_456def789abc"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of notification channel. Currently only 'web_hook' is supported for HTTP POST notifications.",
+ "default": "web_hook"
+ },
+ "address": {
+ "type": "string",
+ "description": "The HTTPS URL where notifications will be sent. Must be accessible from Google's servers and support HTTPS.",
+ "minLength": 1,
+ "examples": [
+ "https://myapp.example.com/webhooks/drive/changes",
+ "https://api.company.com/notifications/google-drive",
+ "https://webhook.site/unique-id"
+ ]
+ },
+ "token": {
+ "type": "string",
+ "description": "An optional arbitrary string that will be passed with each notification to verify the source. Use this for basic authentication.",
+ "examples": [
+ "secret_token_abc123",
+ "webhook_verification_key",
+ "my_custom_auth_token"
+ ]
+ },
+ "expiration": {
+ "type": "integer",
+ "description": "The expiration time of the notification channel as a Unix timestamp in milliseconds. If not provided, defaults to maximum allowed (typically 24 hours).",
+ "minimum": 0,
+ "examples": [
+ 1640995200000,
+ 1641081600000
+ ]
+ },
+ "params": {
+ "type": "object",
+ "description": "Additional parameters controlling delivery channel behavior.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "payload": {
+ "type": "boolean",
+ "description": "Whether payload is included in notifications.",
+ "default": true
+ },
+ "resourceUri": {
+ "type": "string",
+ "description": "A version-specific identifier for the watched resource.",
+ "minLength": 1,
+ "examples": [
+ "resource_123",
+ "resource_456"
+ ]
+ },
+ "resourceId": {
+ "type": "string",
+ "description": "An opaque ID that identifies the resource being watched on this channel.",
+ "minLength": 1,
+ "examples": [
+ "resource_123",
+ "resource_456"
+ ]
+ }
+ },
+ "required": [
+ "pageToken",
+ "id",
+ "address"
+ ],
+ "additionalProperties": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/email.json b/resources_servers/enterpriseops_gym/data/tools/email.json
new file mode 100644
index 0000000000..d07f7df6a5
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/email.json
@@ -0,0 +1,3139 @@
+{
+ "gym_name": "gym-email-mcp",
+ "gym_url": "http://localhost:8004",
+ "snapshot_at": "2026-07-07T18:18:26.710188+00:00",
+ "tools": [
+ {
+ "name": "get_user_profile",
+ "description": "Get profile for a Email user",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "stop_user_watch",
+ "description": "Stop receiving push notifications for the given user mailbox",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "watch_user_mailbox",
+ "description": "Set up or update a push notification watch on the given user mailbox",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "topicName": {
+ "type": "string",
+ "description": "A fully qualified Google Cloud Pub/Sub API topic name. Should be a valid Pub/Sub",
+ "pattern": "^projects\\/[a-z0-9\\-]+\\/topics\\/[a-zA-Z0-9\\-_]+$"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of labelIds to restrict notifications about"
+ },
+ "labelFilterBehavior": {
+ "type": "string",
+ "enum": [
+ "include",
+ "exclude"
+ ],
+ "description": "Filtering behavior of labelIds list"
+ }
+ },
+ "required": [
+ "topicName",
+ "userId",
+ "labelIds"
+ ]
+ }
+ },
+ {
+ "name": "create_draft",
+ "description": "Creates a new draft with the DRAFT label",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "message": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message"
+ },
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ }
+ },
+ "required": [],
+ "oneOf": [
+ {
+ "required": [
+ "raw"
+ ]
+ },
+ {
+ "required": [
+ "payload"
+ ]
+ }
+ ]
+ }
+ },
+ "required": [
+ "message"
+ ]
+ }
+ },
+ {
+ "name": "delete_draft",
+ "description": "Immediately and permanently deletes the specified draft",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the draft to delete"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "get_draft",
+ "description": "Gets the specified draft",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the draft to retrieve"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "format": {
+ "type": "string",
+ "enum": [
+ "minimal",
+ "full",
+ "raw",
+ "metadata"
+ ],
+ "description": "The format to return the draft in",
+ "default": "full"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "list_drafts",
+ "description": "Lists the drafts in the user's mailbox",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of drafts to return (default: 100, max: 500)",
+ "minimum": 1,
+ "maximum": 500,
+ "default": 100
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Page token to retrieve a specific page of results"
+ },
+ "q": {
+ "type": "string",
+ "description": "Only return draft messages matching the specified query"
+ },
+ "includeSpamTrash": {
+ "type": "boolean",
+ "description": "Include drafts from SPAM and TRASH in the results",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "send_draft",
+ "description": "Sends the specified, existing draft to the recipients",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the draft to send"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "message": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message"
+ },
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ }
+ },
+ "required": [],
+ "oneOf": [
+ {
+ "required": [
+ "raw"
+ ]
+ },
+ {
+ "required": [
+ "payload"
+ ]
+ }
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "message"
+ ]
+ }
+ },
+ {
+ "name": "update_draft",
+ "description": "Replaces a draft's content",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the draft to update"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "message": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message"
+ },
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX/Epoch ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "message"
+ ]
+ }
+ },
+ {
+ "name": "list_history",
+ "description": "Lists the history of all changes to the given mailbox. History results are returned in chronological order (increasing historyId).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "startHistoryId": {
+ "type": "string",
+ "description": "Returns history records after the specified startHistoryId. If not provided or empty, returns all history from the beginning. The startHistoryId should be obtained from the historyId of a message, thread, or previous list response"
+ },
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of history records to return. This field defaults to 100. The maximum allowed value for this field is 500",
+ "minimum": 1,
+ "maximum": 500,
+ "default": 100
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Page token to retrieve a specific page of results in the list"
+ },
+ "labelId": {
+ "type": "string",
+ "description": "Only return messages with a label matching the ID"
+ },
+ "historyTypes": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "messageAdded",
+ "messageDeleted",
+ "labelAdded",
+ "labelRemoved"
+ ]
+ },
+ "description": "History types to be returned by the function"
+ }
+ },
+ "required": [
+ "userId",
+ "startHistoryId"
+ ]
+ }
+ },
+ {
+ "name": "create_label",
+ "description": "Creates a new label",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "name": {
+ "type": "string",
+ "description": "The display name of the label"
+ },
+ "messageListVisibility": {
+ "type": "string",
+ "enum": [
+ "show",
+ "hide"
+ ],
+ "description": "The visibility of messages with this label in the message list",
+ "default": "show"
+ },
+ "labelListVisibility": {
+ "type": "string",
+ "enum": [
+ "labelShow",
+ "labelShowIfUnread",
+ "labelHide"
+ ],
+ "description": "The visibility of the label in the label list",
+ "default": "labelShow"
+ },
+ "color": {
+ "type": "object",
+ "description": "Color settings for the label (user labels only)",
+ "properties": {
+ "textColor": {
+ "type": "string",
+ "description": "The text color of the label, represented as hex string. This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "The background color represented as hex string #RRGGBB (ex #000000). This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ }
+ }
+ }
+ },
+ "required": [
+ "name",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "delete_label",
+ "description": "Immediately and permanently deletes the specified label and removes it from any messages and threads",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the label to delete"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "get_label",
+ "description": "Gets the specified label",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the label to retrieve"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "list_labels",
+ "description": "Lists all labels in the user's mailbox",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "patch_label",
+ "description": "Patch the specified label (partial update)",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the label to update"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "name": {
+ "type": "string",
+ "description": "The display name of the label"
+ },
+ "messageListVisibility": {
+ "type": "string",
+ "enum": [
+ "show",
+ "hide"
+ ],
+ "description": "The visibility of messages with this label in the message list",
+ "default": "show"
+ },
+ "labelListVisibility": {
+ "type": "string",
+ "enum": [
+ "labelShow",
+ "labelShowIfUnread",
+ "labelHide"
+ ],
+ "description": "The visibility of the label in the label list",
+ "default": "labelShow"
+ },
+ "color": {
+ "type": "object",
+ "description": "Color settings for the label (user labels only)",
+ "properties": {
+ "textColor": {
+ "type": "string",
+ "description": "The text color of the label, represented as hex string. This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "The background color represented as hex string #RRGGBB (ex #000000). This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ }
+ }
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_label",
+ "description": "Updates the specified label (full update)",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the label to update"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "name": {
+ "type": "string",
+ "description": "The display name of the label"
+ },
+ "messageListVisibility": {
+ "type": "string",
+ "enum": [
+ "show",
+ "hide"
+ ],
+ "description": "The visibility of messages with this label in the message list",
+ "default": "show"
+ },
+ "labelListVisibility": {
+ "type": "string",
+ "enum": [
+ "labelShow",
+ "labelShowIfUnread",
+ "labelHide"
+ ],
+ "description": "The visibility of the label in the label list",
+ "default": "labelShow"
+ },
+ "color": {
+ "type": "object",
+ "description": "Color settings for the label (user labels only)",
+ "properties": {
+ "textColor": {
+ "type": "string",
+ "description": "The text color of the label, represented as hex string. This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ },
+ "backgroundColor": {
+ "type": "string",
+ "description": "The background color represented as hex string #RRGGBB (ex #000000). This field is required in order to set the color of a label. Only the following predefined set of color values are allowed: #000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #ffffff, #fb4c2f, #ffad47, #fad165, #16a766, #43d692, #4a86e8, #a479e2, #f691b3, #f6c5be, #ffe6c7, #fef1d1, #b9e4d0, #c6f3de, #c9daf8, #e4d7f5, #fcdee8, #efa093, #ffd6a2, #fce8b3, #89d3b2, #a0eac9, #a4c2f4, #d0bcf1, #fbc8d9, #e66550, #ffbc6b, #fcda83, #44b984, #68dfa9, #6d9eeb, #b694e8, #f7a7c0, #cc3a21, #eaa041, #f2c960, #149e60, #3dc789, #3c78d8, #8e63ce, #e07798, #ac2b16, #cf8933, #d5ae49, #0b804b, #2a9c68, #285bac, #653e9b, #b65775, #822111, #a46a21, #aa8831, #076239, #1a764d, #1c4587, #41236d, #83334c, #464646, #e7e7e7, #0d3472, #b6cff5, #0d3b44, #98d7e4, #3d188e, #e3d7ff, #711a36, #fbd3e0, #8a1c0a, #f2b2a8, #7a2e0b, #ffc8af, #7a4706, #ffdeb5, #594c05, #fbe983, #684e07, #fdedc1, #0b4f30, #b3efd3, #04502e, #a2dcc1, #c2c2c2, #4986e7, #2da2bb, #b99aff, #994a64, #f691b2, #ff7537, #ffad46, #662e37, #ebdbde, #cca6ac, #094228, #42d692, #16a765"
+ }
+ }
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "messageListVisibility",
+ "labelListVisibility",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "batch_delete_messages",
+ "description": "Delete many messages by message ID. Provides no guarantees that messages were not already deleted or even existed at all.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "ids": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The IDs of the messages to delete",
+ "maxItems": 1000
+ }
+ },
+ "required": [
+ "userId",
+ "ids"
+ ]
+ }
+ },
+ {
+ "name": "batch_modify_messages",
+ "description": "Modify the labels on the specified messages",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "ids": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The IDs of the messages to modify. There is a limit of 1000 ids per request",
+ "maxItems": 1000
+ },
+ "addLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list of label IDs to add to messages",
+ "default": []
+ },
+ "removeLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list of label IDs to remove from messages",
+ "default": []
+ }
+ },
+ "required": [
+ "ids"
+ ]
+ }
+ },
+ {
+ "name": "delete_message",
+ "description": "Immediately and permanently delete the specified message. This operation cannot be undone. Prefer trash_message instead.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the message to delete"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "get_message",
+ "description": "Get the specified message",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the message to retrieve"
+ },
+ "format": {
+ "type": "string",
+ "enum": [
+ "minimal",
+ "full",
+ "raw",
+ "metadata"
+ ],
+ "description": "The format to return the message in",
+ "default": "full"
+ },
+ "metadataHeaders": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "When given and format is METADATA, only include headers specified",
+ "default": []
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "import_message",
+ "description": "Import a message into this user's mailbox (like receiving via SMTP). Provide exactly ONE message source: ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ },
+ "internalDateSource": {
+ "type": "string",
+ "enum": [
+ "receivedTime",
+ "dateHeader"
+ ],
+ "description": "Source for Email's internal date of the message",
+ "default": "receivedTime"
+ },
+ "neverMarkSpam": {
+ "type": "boolean",
+ "description": "Ignore the Email spam classifier decision and never mark this email as SPAM",
+ "default": false
+ },
+ "processForCalendar": {
+ "type": "boolean",
+ "description": "Process calendar invites in the email and add any extracted meetings to the Google Calendar",
+ "default": false
+ },
+ "deleted": {
+ "type": "boolean",
+ "description": "Mark the email as permanently deleted (not TRASH) and only visible in Google Vault",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "insert_message",
+ "description": "Directly insert a message into only this user's mailbox similar to IMAP APPEND, bypassing most scanning and classification. Does not send a message.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ },
+ "internalDateSource": {
+ "type": "string",
+ "enum": [
+ "receivedTime",
+ "dateHeader"
+ ],
+ "description": "Source for Email's internal date of the message",
+ "default": "receivedTime"
+ },
+ "deleted": {
+ "type": "boolean",
+ "description": "Mark the email as permanently deleted (not TRASH) and only visible in Google Vault",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "list_messages",
+ "description": "List the messages in the user's mailbox",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "maxResults": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 500,
+ "description": "Maximum number of messages to return. This field defaults to 100",
+ "default": 100
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Page token to retrieve a specific page of results in the list"
+ },
+ "q": {
+ "type": "string",
+ "description": "Only return messages matching the specified query. Supports the same query format as the Email search box"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Only return messages with labels that match all of the specified label IDs",
+ "default": []
+ },
+ "includeSpamTrash": {
+ "type": "boolean",
+ "description": "Include messages from SPAM and TRASH in the results",
+ "default": false
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "modify_message",
+ "description": "Modify the labels on the specified message",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message to modify"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "addLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list of IDs of labels to add to this message. You can add up to 100 labels with each update",
+ "maxItems": 100,
+ "default": []
+ },
+ "removeLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list IDs of labels to remove from this message. You can remove up to 100 labels with each update",
+ "maxItems": 100,
+ "default": []
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "send_message",
+ "description": "Send an email from this user. Provide exactly ONE message source: (1) 'raw' (RFC 2822 base64url), (2) 'payload' (Email-like parts with non-empty headers), or ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "threadId": {
+ "type": "string",
+ "description": "The ID of the thread the message belongs to"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of IDs of labels to apply to this message",
+ "default": []
+ },
+ "snippet": {
+ "type": "string",
+ "description": "A short snippet of the message content"
+ },
+ "historyId": {
+ "type": "string",
+ "description": "The ID of the last history record that modified this message"
+ },
+ "internalDate": {
+ "type": "string",
+ "description": "The internal date of the message in UNIX ms timestamp format"
+ },
+ "payload": {
+ "type": "object",
+ "description": "The parsed email structure in the message parts",
+ "properties": {
+ "partId": {
+ "type": "string",
+ "description": "The MIME part ID"
+ },
+ "mimeType": {
+ "type": "string",
+ "description": "The MIME type of the message part"
+ },
+ "filename": {
+ "type": "string",
+ "description": "The filename of the attachment (if any)"
+ },
+ "headers": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "properties": {
+ "attachmentId": {
+ "type": "string",
+ "description": "The ID of the attachment"
+ },
+ "size": {
+ "type": "integer",
+ "description": "Size of the body in bytes, must be greater than 0"
+ },
+ "data": {
+ "type": "string",
+ "description": "The body data of the message part, required"
+ }
+ },
+ "required": [
+ "data",
+ "size"
+ ]
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Child message parts (for multipart messages)"
+ }
+ }
+ }
+ },
+ "sizeEstimate": {
+ "type": "integer",
+ "description": "Estimated size of the message in bytes"
+ },
+ "raw": {
+ "type": "string",
+ "description": "The entire email message in an RFC 2822 formatted and base64url encoded string"
+ }
+ },
+ "required": [
+ "userId"
+ ],
+ "oneOf": [
+ {
+ "required": [
+ "raw"
+ ]
+ },
+ {
+ "required": [
+ "payload"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "trash_message",
+ "description": "Move the specified message to the trash",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message to Trash"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "untrash_message",
+ "description": "Remove the specified message from the trash",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the message to remove from Trash"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "get_attachment",
+ "description": "Get the specified attachment from a message",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "messageId": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The ID of the message containing the attachment"
+ },
+ "id": {
+ "type": "string",
+ "minLength": 1,
+ "description": "The ID of the attachment to retrieve"
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "messageId",
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "get_auto_forwarding",
+ "description": "Get the auto-forwarding setting for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_auto_forwarding",
+ "description": "Update the auto-forwarding setting for the specified account. A verified forwarding address must be specified when auto-forwarding is enabled.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether all incoming mail is automatically forwarded to another address",
+ "default": false
+ },
+ "emailAddress": {
+ "type": "string",
+ "description": "Email address to which all incoming messages are forwarded. This email address must be a verified member of the forwarding addresses"
+ },
+ "disposition": {
+ "type": "string",
+ "enum": [
+ "leaveInInbox",
+ "archive",
+ "trash",
+ "markRead"
+ ],
+ "description": "The state that a message should be left in after it has been forwarded",
+ "default": "leaveInInbox"
+ }
+ },
+ "required": [
+ "userId",
+ "emailAddress",
+ "enabled",
+ "disposition"
+ ]
+ }
+ },
+ {
+ "name": "get_imap_settings",
+ "description": "Get IMAP settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_imap_settings",
+ "description": "Update IMAP settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether IMAP is enabled for the account",
+ "default": true
+ },
+ "autoExpunge": {
+ "type": "boolean",
+ "description": "If this value is true, Email will immediately expunge a message when it is marked as deleted in IMAP",
+ "default": true
+ },
+ "expungeBehavior": {
+ "type": "string",
+ "enum": [
+ "archive",
+ "trash",
+ "deleteForever"
+ ],
+ "description": "The action that will be executed on a message when it is marked as deleted and expunged from the last visible IMAP folder",
+ "default": "archive"
+ },
+ "maxFolderSize": {
+ "type": "string",
+ "enum": [
+ "0",
+ "1000",
+ "2000",
+ "5000",
+ "10000"
+ ],
+ "description": "An optional limit on the number of messages that an IMAP folder may contain. A value of zero is interpreted to mean that there is no limit",
+ "default": "0"
+ }
+ },
+ "required": [
+ "userId",
+ "enabled",
+ "autoExpunge",
+ "expungeBehavior",
+ "maxFolderSize"
+ ]
+ }
+ },
+ {
+ "name": "get_language_settings",
+ "description": "Get language settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_language_settings",
+ "description": "Update language settings for the specified account. The language to display Email in, formatted as an RFC 3066 Language Tag",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "displayLanguage": {
+ "type": "string",
+ "description": "The language to display Email in, formatted as an RFC 3066 Language Tag (for example en-GB, fr or ja for British English, French, or Japanese respectively)",
+ "pattern": "^[a-z]{2,3}(-[A-Z]{2})?(-[a-zA-Z0-9]{1,8})*$",
+ "default": "en"
+ }
+ },
+ "required": [
+ "userId",
+ "displayLanguage"
+ ]
+ }
+ },
+ {
+ "name": "get_pop_settings",
+ "description": "Get POP settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_pop_settings",
+ "description": "Update POP settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "accessWindow": {
+ "type": "string",
+ "enum": [
+ "disabled",
+ "fromNowOn",
+ "allMail"
+ ],
+ "description": "The range of messages which are accessible via POP",
+ "default": "disabled"
+ },
+ "disposition": {
+ "type": "string",
+ "enum": [
+ "leaveInInbox",
+ "archive",
+ "trash",
+ "markRead"
+ ],
+ "description": "The action that will be executed on a message after it has been fetched via POP",
+ "default": "leaveInInbox"
+ }
+ },
+ "required": [
+ "userId",
+ "accessWindow",
+ "disposition"
+ ]
+ }
+ },
+ {
+ "name": "get_vacation_settings",
+ "description": "Get vacation responder settings for the specified account",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_vacation_settings",
+ "description": "Update vacation responder settings for the specified account. These settings correspond to the 'Vacation responder' feature in the web interface",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "enableAutoReply": {
+ "type": "boolean",
+ "description": "Flag that controls whether Email automatically replies to messages (required field)",
+ "default": false
+ },
+ "responseSubject": {
+ "type": "string",
+ "description": "Optional text to prepend to the subject line in vacation responses. Required if enableAutoReply is true and responseBodyPlainText/responseBodyHtml are not provided"
+ },
+ "responseBodyPlainText": {
+ "type": "string",
+ "description": "Response body in plain text format. Required if enableAutoReply is true and responseSubject/responseBodyHtml are not provided"
+ },
+ "responseBodyHtml": {
+ "type": "string",
+ "description": "Response body in HTML format. Required if enableAutoReply is true and responseSubject/responseBodyPlainText are not provided. If both responseBodyPlainText and responseBodyHtml are specified, responseBodyHtml will be used"
+ },
+ "restrictToContacts": {
+ "type": "boolean",
+ "description": "Flag that determines whether responses are sent to recipients who are not in the user's list of contacts. Optional, defaults to false",
+ "default": true
+ },
+ "restrictToDomain": {
+ "type": "boolean",
+ "description": "Flag that determines whether responses are sent to recipients who are outside of the user's domain. This feature is only available for Google Workspace users. Optional, defaults to false",
+ "default": true
+ },
+ "startTime": {
+ "type": "string",
+ "description": "An optional start time for sending auto-replies in ISO 8601 format (e.g., '2025-08-30T09:00:00Z'). When this is specified, Email will automatically reply only to messages that it receives after the start time"
+ },
+ "endTime": {
+ "type": "string",
+ "description": "An optional end time for sending auto-replies in ISO 8601 format (e.g., '2025-09-05T18:00:00Z'). When this is specified, Email will automatically reply only to messages that it receives before the end time"
+ }
+ },
+ "required": [
+ "userId",
+ "enableAutoReply",
+ "responseSubject",
+ "responseBodyPlainText",
+ "responseBodyHtml",
+ "restrictToContacts",
+ "restrictToDomain",
+ "startTime",
+ "endTime"
+ ]
+ }
+ },
+ {
+ "name": "create_cse_identity",
+ "description": "Creates and configures a client-side encryption identity that's authorized to send mail from the user account. Email publishes the S/MIME certificate to a shared domain-wide directory so that people within a Google Workspace organization can encrypt and send mail to the identity",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me."
+ },
+ "emailAddress": {
+ "type": "string",
+ "description": "The email address for the sending identity. The email address must be the primary email address of the authenticated user.",
+ "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
+ },
+ "primaryKeyPairId": {
+ "type": "string",
+ "description": "If a key pair is associated, the ID of the key pair, CseKeyPair"
+ },
+ "signAndEncryptKeyPairs": {
+ "type": "object",
+ "description": "The configuration of a CSE identity that uses different key pairs for signing and encryption.",
+ "properties": {
+ "signingKeyPairId": {
+ "type": "string",
+ "description": "The ID of the CseKeyPair that signs outgoing mail."
+ },
+ "encryptionKeyPairId": {
+ "type": "string",
+ "description": "The ID of the CseKeyPair that encrypts signed outgoing mail."
+ }
+ }
+ }
+ },
+ "required": [
+ "emailAddress",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "delete_cse_identity",
+ "description": "Deletes a client-side encryption identity. The authenticated user can no longer use the identity to send encrypted messages. You cannot restore the identity after you delete it",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me."
+ },
+ "cseEmailAddress": {
+ "type": "string",
+ "description": "The primary email address associated with the client-side encryption identity configuration that's removed."
+ }
+ },
+ "required": [
+ "cseEmailAddress",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "get_cse_identity",
+ "description": "Retrieves a client-side encryption identity configuration",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me."
+ },
+ "cseEmailAddress": {
+ "type": "string",
+ "description": "The primary email address associated with the client-side encryption identity configuration that's removed."
+ }
+ },
+ "required": [
+ "cseEmailAddress",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "list_cse_identities",
+ "description": "Lists the client-side encrypted identities for an authenticated user",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me."
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Pagination token indicating which page of identities to return. If the token is not supplied, then the API will return the first page of results."
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The number of identities to return. If not provided, the page size will default to 20 entries.",
+ "default": 20,
+ "minimum": 1,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "patch_cse_identity",
+ "description": "Associates a different key pair with an existing client-side encryption identity. The updated key pair must validate against Google's S/MIME certificate profiles",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me."
+ },
+ "emailAddress": {
+ "type": "string",
+ "description": "The email address for the sending identity. The email address must be the primary email address of the authenticated user."
+ },
+ "primaryKeyPairId": {
+ "type": "string",
+ "description": "If a key pair is associated, the ID of the key pair, CseKeyPair"
+ },
+ "signAndEncryptKeyPairs": {
+ "type": "object",
+ "description": "The configuration of a CSE identity that uses different key pairs for signing and encryption.",
+ "properties": {
+ "signingKeyPairId": {
+ "type": "string",
+ "description": "The ID of the CseKeyPair that signs outgoing mail."
+ },
+ "encryptionKeyPairId": {
+ "type": "string",
+ "description": "The ID of the CseKeyPair that encrypts signed outgoing mail."
+ }
+ }
+ }
+ },
+ "required": [
+ "emailAddress",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "email_create_cse_keypair",
+ "description": "Creates and uploads a client-side encryption S/MIME public key certificate chain and private key metadata for the authenticated user",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "pkcs7": {
+ "type": "string",
+ "description": "The public key and its certificate chain in PKCS#7 format, PEM encoding. Must include -----BEGIN and -----END headers."
+ },
+ "privateKeyMetadata": {
+ "type": "array",
+ "description": "Metadata for private key instances (optional)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "kaclsKeyMetadata": {
+ "type": "object",
+ "properties": {
+ "kaclsUri": {
+ "type": "string",
+ "description": "The kaclsUri of the key access control list service (should be a valid url)",
+ "pattern": "^https://.*"
+ },
+ "kaclsData": {
+ "type": "string",
+ "description": "Opaque data generated by the key access control list service"
+ }
+ },
+ "required": [
+ "kaclsUri",
+ "kaclsData"
+ ]
+ },
+ "hardwareKeyMetadata": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "description": "Description about the hardware key",
+ "minLength": 10
+ }
+ },
+ "required": [
+ "description"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "userId",
+ "pkcs7"
+ ]
+ }
+ },
+ {
+ "name": "email_disable_cse_keypair",
+ "description": "Turns off a client-side encryption key pair. The authenticated user can no longer use the key pair to decrypt incoming CSE message texts or sign outgoing CSE mail.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "keyPairId": {
+ "type": "string",
+ "description": "The identifier of the key pair to turn off"
+ }
+ },
+ "required": [
+ "userId",
+ "keyPairId"
+ ]
+ }
+ },
+ {
+ "name": "email_enable_cse_keypair",
+ "description": "Turns on a client-side encryption key pair that was turned off. The key pair becomes active again for any associated client-side encryption identities.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "keyPairId": {
+ "type": "string",
+ "description": "The identifier of the key pair to turn on"
+ }
+ },
+ "required": [
+ "userId",
+ "keyPairId"
+ ]
+ }
+ },
+ {
+ "name": "email_get_cse_keypair",
+ "description": "Retrieves an existing client-side encryption key pair.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "keyPairId": {
+ "type": "string",
+ "description": "The identifier of the key pair to retrieve"
+ }
+ },
+ "required": [
+ "userId",
+ "keyPairId"
+ ]
+ }
+ },
+ {
+ "name": "email_list_cse_keypairs",
+ "description": "Lists client-side encryption key pairs for an authenticated user.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Pagination token indicating which page of key pairs to return. If the token is not supplied, then the API will return the first page of results."
+ },
+ "pageSize": {
+ "type": "integer",
+ "description": "The number of key pairs to return. If not provided, the page size will default to 20 entries.",
+ "minimum": 1,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "email_obliterate_cse_keypair",
+ "description": "Deletes a client-side encryption key pair permanently and immediately. You can only permanently delete key pairs that have been turned off for more than 30 days.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "The requester's primary email address. To indicate the authenticated user, you can use the special value me.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "keyPairId": {
+ "type": "string",
+ "description": "The identifier of the key pair to obliterate"
+ }
+ },
+ "required": [
+ "userId",
+ "keyPairId"
+ ]
+ }
+ },
+ {
+ "name": "email_create_delegate",
+ "description": "Adds a delegate with its verification status automatically set to accepted, without sending any verification email. The delegate user must be a member of the same Google Workspace organization as the delegator user.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user."
+ },
+ "delegateEmail": {
+ "type": "string",
+ "description": "The email address of the delegate."
+ }
+ },
+ "required": [
+ "userId",
+ "delegateEmail"
+ ]
+ }
+ },
+ {
+ "name": "email_delete_delegate",
+ "description": "Removes the specified delegate (which can be of any verification status), and revokes any verification that may have been required for using it.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user."
+ },
+ "delegateEmail": {
+ "type": "string",
+ "description": "The email address of the delegate."
+ }
+ },
+ "required": [
+ "userId",
+ "delegateEmail"
+ ]
+ }
+ },
+ {
+ "name": "email_get_delegate",
+ "description": "Gets the specified delegate. Note that a delegate user must be referred to by their primary email address, and not an email alias.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user."
+ },
+ "delegateEmail": {
+ "type": "string",
+ "description": "The email address of the delegate."
+ }
+ },
+ "required": [
+ "userId",
+ "delegateEmail"
+ ]
+ }
+ },
+ {
+ "name": "email_list_delegates",
+ "description": "Lists the delegates for the specified account. Returns delegates with any verification status.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "create_filter",
+ "description": "Creates a filter. Note: you can only create a maximum of 1,000 filters",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "criteria": {
+ "type": "object",
+ "properties": {
+ "from": {
+ "type": "string",
+ "description": "The sender's display name or email address"
+ },
+ "to": {
+ "type": "string",
+ "description": "The recipient's display name or email address"
+ },
+ "subject": {
+ "type": "string",
+ "description": "Case-insensitive phrase found in the message's subject"
+ },
+ "query": {
+ "type": "string",
+ "description": "Only return messages matching the specified query"
+ },
+ "negatedQuery": {
+ "type": "string",
+ "description": "Only return messages not matching the specified query"
+ },
+ "hasAttachment": {
+ "type": "boolean",
+ "description": "Whether the message has any attachment",
+ "default": true
+ },
+ "excludeChats": {
+ "type": "boolean",
+ "description": "Whether the response should exclude chats",
+ "default": true
+ },
+ "size": {
+ "type": "integer",
+ "description": "The size of the entire RFC822 message in bytes"
+ },
+ "sizeComparison": {
+ "type": "string",
+ "enum": [
+ "unspecified",
+ "smaller",
+ "larger"
+ ],
+ "description": "How the message size should be compared to the size field"
+ }
+ },
+ "description": "Message matching criteria for the filter",
+ "required": [
+ "from",
+ "to",
+ "subject",
+ "query",
+ "negatedQuery",
+ "hasAttachment",
+ "excludeChats",
+ "size",
+ "sizeComparison"
+ ]
+ },
+ "action": {
+ "type": "object",
+ "properties": {
+ "addLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of labels to add to the message"
+ },
+ "removeLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "List of labels to remove from the message"
+ },
+ "forward": {
+ "type": "string",
+ "description": "Email address that the message should be forwarded to"
+ }
+ },
+ "description": "Action that the filter performs"
+ }
+ },
+ "required": [
+ "userId",
+ "criteria",
+ "action"
+ ]
+ }
+ },
+ {
+ "name": "delete_filter",
+ "description": "Immediately and permanently deletes the specified filter",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the filter to delete"
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "get_filter",
+ "description": "Gets a filter",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the filter to retrieve"
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "list_filters",
+ "description": "Lists the message filters of a Email user",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "create_forwarding_address",
+ "description": "Creates a forwarding address. If ownership verification is required, a message will be sent to the recipient and the resource's verification status will be set to pending; otherwise, the resource will be created with verification status set to accepted. The verification status is determined automatically by the system based on domain ownership.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "forwardingEmail": {
+ "type": "string",
+ "description": "An email address to which messages can be forwarded",
+ "format": "email"
+ }
+ },
+ "required": [
+ "userId",
+ "forwardingEmail"
+ ]
+ }
+ },
+ {
+ "name": "delete_forwarding_address",
+ "description": "Deletes the specified forwarding address and revokes any verification that may have been required.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "forwardingEmail": {
+ "type": "string",
+ "description": "The forwarding address to be deleted.",
+ "format": "email"
+ }
+ },
+ "required": [
+ "userId",
+ "forwardingEmail"
+ ]
+ }
+ },
+ {
+ "name": "get_forwarding_address",
+ "description": "Gets the specified forwarding address.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "forwardingEmail": {
+ "type": "string",
+ "description": "The forwarding address to be retrieved.",
+ "format": "email"
+ }
+ },
+ "required": [
+ "userId",
+ "forwardingEmail"
+ ]
+ }
+ },
+ {
+ "name": "list_forwarding_addresses",
+ "description": "Lists the forwarding addresses for the specified account.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value \"me\" can be used to indicate the authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "create_send_as_alias",
+ "description": "Creates a custom \"from\" send-as alias. Note: If an SMTP MSA is specified, Email will attempt to connect to the SMTP service to validate the configuration before creating the alias. If ownership verification is required for the alias, a message will be sent to the email address and the resource's verification status will be set to pending; otherwise, the resource will be created with verification status set to accepted. If a signature is provided, Email will sanitize the HTML before saving it with the alias. This method is only available to service account clients that have been delegated domain-wide authority.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias. This is read-only for all operations except create."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "A name that appears in the \"From:\" header for mail sent using this alias. For custom \"from\" addresses, when this is empty, Email will populate the \"From:\" header with the name that is used for the primary address associated with the account."
+ },
+ "replyToAddress": {
+ "type": "string",
+ "description": "An optional email address that is included in a \"Reply-To:\" header for mail sent using this alias. If this is empty, Email will not generate a \"Reply-To:\" header.",
+ "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
+ },
+ "signature": {
+ "type": "string",
+ "description": "An optional HTML signature that is included in messages composed with this alias in the Email web UI. This signature is added to new emails only."
+ },
+ "isDefault": {
+ "type": "boolean",
+ "description": "Whether this address is selected as the default \"From:\" address in situations such as composing a new message or sending a vacation auto-reply. Every Email account has exactly one default send-as address, so the only legal value that clients may write to this field is true."
+ },
+ "treatAsAlias": {
+ "type": "boolean",
+ "description": "Whether Email should treat this address as an alias for the user's primary email address. This setting only applies to custom \"from\" aliases."
+ },
+ "smtpMsa": {
+ "type": "object",
+ "description": "An optional SMTP service that will be used as an outbound relay for mail sent using this alias. If this is empty, outbound mail will be sent directly from Email's servers to the destination SMTP service. This setting only applies to custom \"from\" aliases.",
+ "properties": {
+ "host": {
+ "type": "string",
+ "description": "The hostname of the SMTP service. Required."
+ },
+ "port": {
+ "type": "integer",
+ "description": "The port of the SMTP service. Required."
+ },
+ "username": {
+ "type": "string",
+ "description": "The username that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "password": {
+ "type": "string",
+ "description": "The password that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "securityMode": {
+ "type": "string",
+ "enum": [
+ "securityModeUnspecified",
+ "none",
+ "ssl",
+ "starttls"
+ ],
+ "description": "The protocol that will be used to secure communication with the SMTP service. Required."
+ }
+ },
+ "required": [
+ "host",
+ "port",
+ "securityMode"
+ ]
+ }
+ },
+ "required": [
+ "sendAsEmail"
+ ]
+ }
+ },
+ {
+ "name": "delete_send_as_alias",
+ "description": "Deletes the specified send-as alias. Revokes any verification that may have been required for using it. This method is only available to service account clients that have been delegated domain-wide authority.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The send-as alias to be deleted."
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId",
+ "sendAsEmail"
+ ]
+ }
+ },
+ {
+ "name": "get_send_as_alias",
+ "description": "Gets the specified send-as alias. Fails with an HTTP 404 error if the specified address is not a member of the collection.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The send-as alias to be retrieved."
+ },
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ }
+ },
+ "required": [
+ "userId",
+ "sendAsEmail"
+ ]
+ }
+ },
+ {
+ "name": "list_send_as_aliases",
+ "description": "Lists the send-as aliases for the specified account. The result includes the primary send-as address associated with the account as well as any custom \"from\" aliases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value 'me' can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "patch_send_as_alias",
+ "description": "Patch the specified send-as alias. Only the fields that are provided will be updated.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The send-as alias to be updated"
+ },
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value 'me' can be used to indicate the authenticated user."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "A name that appears in the 'From:' header for mail sent using this alias. For custom 'from' addresses, when this is empty, Gmail will populate the 'From:' header with the name that is used for the primary address associated with the account. If the admin has disabled the ability for users to update their name format, requests to update this field for the primary login will silently fail."
+ },
+ "replyToAddress": {
+ "type": "string",
+ "description": "An optional email address that is included in a 'Reply-To:' header for mail sent using this alias. If this is empty, Gmail will not generate a 'Reply-To:' header."
+ },
+ "signature": {
+ "type": "string",
+ "description": "An optional HTML signature that is included in messages composed with this alias in the Gmail web UI. This signature is added to new emails only."
+ },
+ "isDefault": {
+ "type": "boolean",
+ "description": "Whether this address is selected as the default 'From:' address in situations such as composing a new message or sending a vacation auto-reply. Every Gmail account has exactly one default send-as address, so the only legal value that clients may write to this field is true. Changing this from false to true for an address will result in this field becoming false for the other previous default address."
+ },
+ "treatAsAlias": {
+ "type": "boolean",
+ "description": "Whether Gmail should treat this address as an alias for the user's primary email address. This setting only applies to custom 'from' aliases."
+ },
+ "smtpMsa": {
+ "type": "object",
+ "description": "An optional SMTP service that will be used as an outbound relay for mail sent using this alias. If this is empty, outbound mail will be sent directly from Gmail's servers to the destination SMTP service. This setting only applies to custom 'from' aliases.",
+ "properties": {
+ "host": {
+ "type": "string",
+ "description": "The hostname of the SMTP service. Required."
+ },
+ "port": {
+ "type": "integer",
+ "description": "The port of the SMTP service. Required."
+ },
+ "username": {
+ "type": "string",
+ "description": "The username that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "password": {
+ "type": "string",
+ "description": "The password that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "securityMode": {
+ "type": "string",
+ "enum": [
+ "securityModeUnspecified",
+ "none",
+ "ssl",
+ "starttls"
+ ],
+ "description": "The protocol that will be used to secure communication with the SMTP service. Required."
+ }
+ },
+ "required": [
+ "host",
+ "port",
+ "securityMode"
+ ]
+ },
+ "verificationStatus": {
+ "type": "string",
+ "enum": [
+ "verificationStatusUnspecified",
+ "accepted",
+ "pending"
+ ],
+ "description": "Indicates whether this address has been verified for use as a send-as alias. Read-only. This setting only applies to custom 'from' aliases."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "update_send_as_alias",
+ "description": "Updates a send-as alias. If a signature is provided, Email will sanitize the HTML before saving it with the alias. Addresses other than the primary address for the account can only be updated by service account clients that have been delegated domain-wide authority.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The send-as alias to be updated"
+ },
+ "userId": {
+ "type": "string",
+ "description": "User's email address. The special value 'me' can be used to indicate the authenticated user."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "A name that appears in the 'From:' header for mail sent using this alias. For custom 'from' addresses, when this is empty, Gmail will populate the 'From:' header with the name that is used for the primary address associated with the account. If the admin has disabled the ability for users to update their name format, requests to update this field for the primary login will silently fail."
+ },
+ "replyToAddress": {
+ "type": "string",
+ "description": "An optional email address that is included in a 'Reply-To:' header for mail sent using this alias. If this is empty, Gmail will not generate a 'Reply-To:' header."
+ },
+ "signature": {
+ "type": "string",
+ "description": "An optional HTML signature that is included in messages composed with this alias in the Gmail web UI. This signature is added to new emails only."
+ },
+ "isDefault": {
+ "type": "boolean",
+ "description": "Whether this address is selected as the default 'From:' address in situations such as composing a new message or sending a vacation auto-reply. Every Gmail account has exactly one default send-as address, so the only legal value that clients may write to this field is true. Changing this from false to true for an address will result in this field becoming false for the other previous default address."
+ },
+ "treatAsAlias": {
+ "type": "boolean",
+ "description": "Whether Gmail should treat this address as an alias for the user's primary email address. This setting only applies to custom 'from' aliases."
+ },
+ "smtpMsa": {
+ "type": "object",
+ "description": "An optional SMTP service that will be used as an outbound relay for mail sent using this alias. If this is empty, outbound mail will be sent directly from Gmail's servers to the destination SMTP service. This setting only applies to custom 'from' aliases.",
+ "properties": {
+ "host": {
+ "type": "string",
+ "description": "The hostname of the SMTP service. Required."
+ },
+ "port": {
+ "type": "integer",
+ "description": "The port of the SMTP service. Required."
+ },
+ "username": {
+ "type": "string",
+ "description": "The username that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "password": {
+ "type": "string",
+ "description": "The password that will be used for authentication with the SMTP service. This is a write-only field that can be specified in requests to create or update SendAs settings; it is never populated in responses."
+ },
+ "securityMode": {
+ "type": "string",
+ "enum": [
+ "securityModeUnspecified",
+ "none",
+ "ssl",
+ "starttls"
+ ],
+ "description": "The protocol that will be used to secure communication with the SMTP service. Required."
+ }
+ },
+ "required": [
+ "host",
+ "port",
+ "securityMode"
+ ]
+ },
+ "verificationStatus": {
+ "type": "string",
+ "enum": [
+ "verificationStatusUnspecified",
+ "accepted",
+ "pending"
+ ],
+ "description": "Indicates whether this address has been verified for use as a send-as alias. Read-only. This setting only applies to custom 'from' aliases."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "userId",
+ "displayName",
+ "replyToAddress",
+ "signature",
+ "isDefault",
+ "treatAsAlias",
+ "smtpMsa",
+ "verificationStatus"
+ ]
+ }
+ },
+ {
+ "name": "verify_send_as_alias",
+ "description": "Sends a verification email to the specified send-as alias address. The verification status must be pending. This method is only available to service account clients that have been delegated domain-wide authority.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The send-as alias to be verified."
+ }
+ },
+ "required": [
+ "userId",
+ "sendAsEmail"
+ ]
+ }
+ },
+ {
+ "name": "delete_smime_config",
+ "description": "Deletes the specified S/MIME config for the specified send-as alias.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias."
+ },
+ "id": {
+ "type": "string",
+ "description": "The immutable ID for the SmimeInfo."
+ },
+ "userId": {
+ "type": "string",
+ "description": "The user's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "get_smime_config",
+ "description": "Gets the specified S/MIME config for the specified send-as alias.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias."
+ },
+ "id": {
+ "type": "string",
+ "description": "The immutable ID for the SmimeInfo."
+ },
+ "userId": {
+ "type": "string",
+ "description": "The user's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "insert_smime_config",
+ "description": "Insert (upload) the given S/MIME config for the specified send-as alias. Note that pkcs12 format is required for the key.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias."
+ },
+ "issuerCn": {
+ "type": "string",
+ "description": "The S/MIME certificate issuer's common name."
+ },
+ "isDefault": {
+ "type": "boolean",
+ "description": "Whether this SmimeInfo is the default one for this user's send-as address."
+ },
+ "expiration": {
+ "type": "string",
+ "description": "When the certificate expires (in milliseconds since epoch)."
+ },
+ "encryptedKeyPassword": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Encrypted key password, when key is encrypted."
+ },
+ "pem": {
+ "type": "string",
+ "description": "PEM formatted X509 concatenated certificate string (standard base64 encoding). Format used for returning key, which includes public key as well as certificate chain (not private key)."
+ },
+ "pkcs12": {
+ "type": "string",
+ "description": "PKCS#12 format containing a single private/public key pair and certificate chain. This format is only accepted from client for creating a new SmimeInfo and is never returned, because the private key is not intended to be exported. PKCS#12 may be encrypted, in which case encryptedKeyPassword should be set appropriately. A base64-encoded string."
+ },
+ "userId": {
+ "type": "string",
+ "description": "The user's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "issuerCn",
+ "expiration",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "list_smime_configs",
+ "description": "Lists S/MIME configs for the specified send-as alias.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias."
+ },
+ "userId": {
+ "type": "string",
+ "description": "The user's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "set_default_smime_config",
+ "description": "Sets the default S/MIME config for the specified send-as alias.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sendAsEmail": {
+ "type": "string",
+ "description": "The email address that appears in the \"From:\" header for mail sent using this alias."
+ },
+ "id": {
+ "type": "string",
+ "description": "The immutable ID for the SmimeInfo."
+ },
+ "userId": {
+ "type": "string",
+ "description": "The user's email address. The special value \"me\" can be used to indicate the authenticated user."
+ }
+ },
+ "required": [
+ "sendAsEmail",
+ "id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "delete_thread",
+ "description": "Immediately and permanently deletes the specified thread. Any messages that belong to the thread are also deleted.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "ID of the Thread to delete."
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "get_thread",
+ "description": "Gets the specified thread.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the thread to retrieve."
+ },
+ "format": {
+ "type": "string",
+ "description": "The format to return the messages in.",
+ "enum": [
+ "minimal",
+ "full",
+ "metadata"
+ ],
+ "default": "full"
+ },
+ "metadataHeaders": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "When given and format is METADATA, only include headers specified."
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "list_threads",
+ "description": "Lists the threads in the user's mailbox.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "maxResults": {
+ "type": "integer",
+ "description": "Maximum number of threads to return. Defaults to 100, max 500.",
+ "minimum": 1,
+ "maximum": 500,
+ "default": 100
+ },
+ "pageToken": {
+ "type": "string",
+ "description": "Page token to retrieve a specific page of results in the list."
+ },
+ "q": {
+ "type": "string",
+ "description": "Only return threads matching the specified query. Supports Email search syntax."
+ },
+ "labelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Only return threads with labels that match all of the specified label IDs."
+ },
+ "includeSpamTrash": {
+ "type": "boolean",
+ "description": "Include threads from SPAM and TRASH in the results.",
+ "default": false
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "modify_thread",
+ "description": "Modifies the labels applied to the thread. This applies to all messages in the thread.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the thread to modify."
+ },
+ "addLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list of IDs of labels to add to this thread. You can add up to 100 labels with each update.",
+ "maxItems": 100
+ },
+ "removeLabelIds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "A list of IDs of labels to remove from this thread. You can remove up to 100 labels with each update.",
+ "maxItems": 100
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "trash_thread",
+ "description": "Moves the specified thread to the trash. Any messages that belong to the thread are also moved to the trash.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the thread to Trash."
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "untrash_thread",
+ "description": "Removes the specified thread from the trash. Any messages that belong to the thread are also removed from the trash.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Specifies the userId by email address or uses me to refer to the currently authenticated user.",
+ "pattern": "^(?:me|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})$"
+ },
+ "id": {
+ "type": "string",
+ "description": "The ID of the thread to remove from Trash."
+ }
+ },
+ "required": [
+ "userId",
+ "id"
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/hr.json b/resources_servers/enterpriseops_gym/data/tools/hr.json
new file mode 100644
index 0000000000..709288107e
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/hr.json
@@ -0,0 +1,4239 @@
+{
+ "gym_name": "sn-hr-internal",
+ "gym_url": "http://localhost:8008",
+ "snapshot_at": "2026-07-07T18:18:28.040573+00:00",
+ "tools": [
+ {
+ "name": "get_hr_service_by_name",
+ "title": null,
+ "description": "Get complete HR service details by unique service name. Returns full service information including all related entities (topic details with category, service template, and visibility criteria). Use this to understand service workflows, requirements, and configuration before creating HR cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_name": {
+ "type": "string",
+ "description": "The unique name of the HR service to retrieve. Examples: 'Employee Onboarding', 'Benefits Enrollment', 'Payroll Support', 'Performance Review', 'Policy Questions'. Must match exactly (case-sensitive)."
+ }
+ },
+ "required": [
+ "service_name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_hr_services",
+ "title": null,
+ "description": "Flexible search for HR services - at least ONE parameter must be provided. Search by ID, fulfillment type, topic, template, criteria, or active status. Returns matching services with all related entities (topic details, service templates, HR criteria) fully expanded.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_service_id": {
+ "type": "string",
+ "description": "Filter by exact service ID (optional)"
+ },
+ "fulfillment_type": {
+ "type": "string",
+ "description": "Filter by exact fulfillment type (optional)",
+ "enum": [
+ "manual",
+ "service_activity",
+ "workflow",
+ "lifecycle event",
+ "advanced",
+ "flow"
+ ]
+ },
+ "topic_detail": {
+ "type": "string",
+ "description": "Filter by topic detail name - partial match, case-insensitive (optional)"
+ },
+ "service_template": {
+ "type": "string",
+ "description": "Filter by service template name - partial match, case-insensitive (optional)"
+ },
+ "hr_criteria": {
+ "type": "string",
+ "description": "Filter by HR criteria name - partial match, case-insensitive (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_new_hr_service",
+ "title": null,
+ "description": "Create a new HR service with complete validation. Validates that service name is unique, fulfillment type is valid, and all referenced entities (topic detail, service template, HR criteria) exist in the database. Returns the created service with all relationships fully expanded. Use this to add new service offerings to the HR service catalog.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_name": {
+ "type": "string",
+ "description": "Unique service name (e.g., 'Leave of Absence Request', 'Equipment Request'). Must be unique across all services."
+ },
+ "fulfillment_type": {
+ "type": "string",
+ "description": "How the service request is fulfilled",
+ "enum": [
+ "manual",
+ "service_activity",
+ "workflow",
+ "lifecycle event",
+ "advanced",
+ "flow"
+ ]
+ },
+ "topic_detail": {
+ "type": "string",
+ "description": "Topic detail name (must exist in database). Example: 'Leave Management', 'New Employee Setup'. Optional."
+ },
+ "service_template": {
+ "type": "string",
+ "description": "Service template name (must exist in database). Example: 'Leave Request Template', 'Onboarding Template'. Optional."
+ },
+ "hr_criteria": {
+ "type": "string",
+ "description": "HR criteria name for visibility/approval (must exist in database). Example: 'HR Team Visibility', 'Admin Only Visibility'. Optional."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the service is active and available. Defaults to true.",
+ "default": true
+ }
+ },
+ "required": [
+ "service_name",
+ "fulfillment_type",
+ "active"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_hr_service",
+ "title": null,
+ "description": "Update an existing HR service with smart change detection. Validates all field changes and prevents unnecessary updates by detecting if fields are already set to the provided values. Updates only the fields provided and automatically sets the updated_at timestamp. Returns the updated service with all relationships fully expanded.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_service_id": {
+ "type": "string",
+ "description": "ID of the HR service to update (must exist in database). Example: 1"
+ },
+ "service_name": {
+ "type": "string",
+ "description": "New service name (any string, must be unique). Optional - only provide if changing."
+ },
+ "fulfillment_type": {
+ "type": "string",
+ "description": "New fulfillment type. Optional - only provide if changing.",
+ "enum": [
+ "manual",
+ "service_activity",
+ "workflow",
+ "lifecycle event",
+ "advanced",
+ "flow"
+ ]
+ },
+ "topic_detail": {
+ "type": "string",
+ "description": "New topic detail name (must exist in database). Optional - only provide if changing. Example: 'Health Insurance'"
+ },
+ "service_template": {
+ "type": "string",
+ "description": "New service template name (must exist in database). Optional - only provide if changing. Example: 'Benefits Template'"
+ },
+ "hr_criteria": {
+ "type": "string",
+ "description": "New HR criteria name (must exist in database). Optional - only provide if changing. Example: 'Manager Approval Required'"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status. Optional - only provide if changing."
+ }
+ },
+ "required": [
+ "hr_service_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "delete_hr_service",
+ "title": null,
+ "description": "Soft delete an HR service by setting its active status to False. Can be identified by either hr_service_id or service_name (or both if they match). If both provided, validates they reference the same service. Validates the service exists and is currently active before deletion. Returns the deactivated service with all relationships fully expanded. Use this to remove services from active catalog while preserving data for audit trail.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_service_id": {
+ "type": "string",
+ "description": "ID of the HR service to delete. Example: '1'. Provide either hr_service_id or service_name (or both if they match)."
+ },
+ "service_name": {
+ "type": "string",
+ "description": "Name of the HR service to delete. Example: 'Old Service'. Provide either hr_service_id or service_name (or both if they match)."
+ }
+ },
+ "required": [
+ "hr_service_id",
+ "service_name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_topic_details",
+ "title": null,
+ "description": "Flexible search for topic details. At least ONE parameter must be provided. Search by ID, name, active status, or topic category. Returns topic details with expanded topic_category relationship.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "topic_detail_id": {
+ "type": "string",
+ "description": "Topic detail ID for exact match (optional)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Topic detail name for partial matching (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "topic_category": {
+ "type": "string",
+ "description": "Filter by topic category name - partial match (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_topic_categories",
+ "title": null,
+ "description": "Flexible search for topic categories. At least ONE parameter must be provided. Search by ID, name, active status, or COE type. Returns topic categories with topic_details count.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "topic_category_id": {
+ "type": "string",
+ "description": "Topic category ID for exact match (optional)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Topic category name for partial matching (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "Filter by COE type - exact match (optional). Valid values: HRIT, Payroll, Talent Management, Total Rewards, Workforce Administration"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_topic_detail",
+ "title": null,
+ "description": "Create a new topic detail. Validates name is unique within organization and topic_category exists if provided. Returns created topic detail with expanded topic_category relationship.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Topic detail name (required, must be unique). Examples: 'New Employee Setup', 'Health Insurance', 'Payroll Changes'"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether topic detail is active (default: true)",
+ "default": true
+ },
+ "topic_category": {
+ "type": "string",
+ "description": "Topic category name (optional, must exist). Examples: 'Onboarding', 'Benefits', 'Payroll'"
+ }
+ },
+ "required": [
+ "name",
+ "active"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_topic_detail",
+ "title": null,
+ "description": "Update an existing topic detail with smart change detection. Only updates fields that have changed. Validates topic_detail_id exists, name is unique if changed, and topic_category exists if provided. Returns updated topic detail with list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "topic_detail_id": {
+ "type": "string",
+ "description": "Topic detail ID to update (required). Example: '1'"
+ },
+ "name": {
+ "type": "string",
+ "description": "New topic detail name (optional, must be unique if changed). Example: 'Updated Topic Name'"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Example: false",
+ "default": true
+ },
+ "topic_category": {
+ "type": "string",
+ "description": "New topic category name (optional, must exist). Example: 'Onboarding'"
+ }
+ },
+ "required": [
+ "topic_detail_id",
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_topic_category",
+ "title": null,
+ "description": "Create a new topic category. Validates name is unique within organization and coe_type is valid enum value. Returns created topic category with timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Topic category name (required, must be unique). Examples: 'Employee Relations', 'Compensation & Benefits', 'Talent Acquisition'"
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "COE type (required). Valid values: HRIT, Payroll, Talent Management, Total Rewards, Workforce Administration",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether topic category is active (default: true)",
+ "default": true
+ }
+ },
+ "required": [
+ "name",
+ "coe_type",
+ "active"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_topic_category",
+ "title": null,
+ "description": "Update an existing topic category with smart change detection. Only updates fields that have changed. Validates topic_category_id exists, name is unique if changed, and coe_type is valid if changed. Returns updated topic category with list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "topic_category_id": {
+ "type": "string",
+ "description": "Topic category ID to update (required). Example: '1'"
+ },
+ "name": {
+ "type": "string",
+ "description": "New topic category name (optional, must be unique if changed). Example: 'Updated Category Name'"
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "New COE type (optional, must be valid). Valid values: HRIT, Payroll, Talent Management, Total Rewards, Workforce Administration",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Example: false",
+ "default": true
+ }
+ },
+ "required": [
+ "topic_category_id",
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_service_template_by_name",
+ "title": null,
+ "description": "Get a service template by name (exact match, case-insensitive). Returns service template with name, change_request_values (JSON), active status, COE type, and org_id.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Service template name to search for (required, case-insensitive). Examples: 'Onboarding Template', 'Payroll Change Request'"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_service_templates",
+ "title": null,
+ "description": "Flexible search for service templates. At least ONE parameter must be provided. Search by ID, name, active status, or COE type. Returns service templates with change_request_values (JSON), COE type, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_template_id": {
+ "type": "string",
+ "description": "Service template ID for exact match (optional)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Service template name for partial matching (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "coe_type": {
+ "type": "string",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ],
+ "description": "Filter by COE (Center of Excellence) type (optional). Must be one of: HRIT, Payroll, Talent Management, Total Rewards, Workforce Administration"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_new_service_template",
+ "title": null,
+ "description": "Create a new service template with validation. Validates that name is unique within organization, coe_type is valid, and change_request_values contains required fields. Returns the created template with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Service template name (must be unique within organization)"
+ },
+ "change_request_values": {
+ "type": "object",
+ "description": "JSON object with change request default values",
+ "properties": {
+ "short_description": {
+ "type": "string",
+ "description": "Short description for the change request"
+ },
+ "category": {
+ "type": "string",
+ "description": "Category for the change request (e.g., 'hr', 'onboarding', 'payroll')"
+ }
+ },
+ "required": [
+ "short_description",
+ "category"
+ ]
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "Center of Excellence type",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether template is active (default: true)",
+ "default": true
+ }
+ },
+ "required": [
+ "name",
+ "change_request_values",
+ "coe_type"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_service_template",
+ "title": null,
+ "description": "Update an existing service template with smart change detection. At least one field must be provided to update. Validates name uniqueness, coe_type validity, and returns list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_template_id": {
+ "type": "string",
+ "description": "ID of service template to update (required)"
+ },
+ "name": {
+ "type": "string",
+ "description": "New service template name (optional, must be unique if changed)"
+ },
+ "change_request_values": {
+ "type": "object",
+ "description": "New change request values dictionary (optional)",
+ "properties": {
+ "short_description": {
+ "type": "string",
+ "description": "Short description for the change request"
+ },
+ "category": {
+ "type": "string",
+ "description": "Category for the change request"
+ }
+ }
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "New COE type (optional)",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional)"
+ }
+ },
+ "required": [
+ "service_template_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_user",
+ "title": null,
+ "description": "Get user by user ID. Returns complete user details including role, contact information, and status. User must exist in the requester's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "The unique ID of the user to retrieve. Example: '1', '42'"
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_user_using_email",
+ "title": null,
+ "description": "Get user by email address. Searches for user with exact email match (case-insensitive) within the organization. Returns complete user details if found.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "The email address of the user to find. Example: 'john.doe@company.com'",
+ "format": "email"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_user_using_name",
+ "title": null,
+ "description": "Get user by first and last name combination. Search is case-sensitive and requires exact match. Returns complete user details if exact name match is found within the organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "first_name": {
+ "type": "string",
+ "description": "User's first name (case-sensitive, must match exactly). Only letters, spaces, hyphens, apostrophes, and periods allowed. Example: 'John', 'Mary-Jane', 'O'Brien'",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name (case-sensitive, must match exactly). Only letters, spaces, hyphens, apostrophes, and periods allowed. Example: 'Doe', 'O'Brien'",
+ "minLength": 1,
+ "maxLength": 60
+ }
+ },
+ "required": [
+ "first_name",
+ "last_name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_users",
+ "title": null,
+ "description": "List users with filtering, pagination, and sorting. Supports text search (email_like, first_name_like, last_name_like), role filtering (roles array), and active status. Returns paginated results with metadata (total_count, returned_count, limit, offset).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "roles": {
+ "type": "array",
+ "description": "Filter by one or more roles. Example: ['admin'], ['admin', 'manager']",
+ "items": {
+ "type": "string",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "employee"
+ ]
+ }
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status. Example: true"
+ },
+ "email_like": {
+ "type": "string",
+ "description": "Email contains text (case-insensitive partial match). Example: 'john' matches 'john@example.com' and 'johnny@test.com'"
+ },
+ "first_name_like": {
+ "type": "string",
+ "description": "First name contains text (case-insensitive). Example: 'jo'"
+ },
+ "last_name_like": {
+ "type": "string",
+ "description": "Last name contains text (case-insensitive). Example: 'sm'"
+ },
+ "limit": {
+ "type": "integer",
+ "description": "Maximum results to return (default: 50, max: 100). Example: 20",
+ "default": 50,
+ "minimum": 1,
+ "maximum": 100
+ },
+ "offset": {
+ "type": "integer",
+ "description": "Skip N records for pagination (default: 0). Example: 20",
+ "default": 0,
+ "minimum": 0
+ },
+ "order_by": {
+ "type": "string",
+ "description": "Field to sort by (default: created_at)",
+ "enum": [
+ "user_id",
+ "first_name",
+ "last_name",
+ "email",
+ "phone",
+ "role",
+ "active",
+ "created_at",
+ "updated_at"
+ ],
+ "default": "created_at"
+ },
+ "order_direction": {
+ "type": "string",
+ "description": "Sort direction (default: asc). Example: 'desc'",
+ "enum": [
+ "asc",
+ "desc"
+ ],
+ "default": "asc"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_user",
+ "title": null,
+ "description": "Create a new user in the HR system. Validates email uniqueness within organization, name combination uniqueness, and role validity. User is automatically assigned to the requester's organization. Returns complete user details including auto-generated ID and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "first_name": {
+ "type": "string",
+ "description": "User's first name (1-60 characters). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*() are not allowed. Examples: 'John', 'Maria', 'Jos\u00e9', 'Mary-Jane', 'O'Brien'",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name (1-60 characters). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*() are not allowed. Examples: 'Doe', 'Garcia', 'O'Brien', 'Van Der Berg'",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "email": {
+ "type": "string",
+ "description": "User's work email address (must be valid RFC-compliant email format and unique within organization). Invalid characters like *&^%#$ in email addresses are not allowed. Examples: 'john.doe@company.com', 'user+tag@example.org'",
+ "format": "email",
+ "maxLength": 120
+ },
+ "phone": {
+ "type": "string",
+ "description": "User's phone number (optional, max 30 characters). Examples: '+1-555-123-4567', '(555) 123-4567'",
+ "maxLength": 30
+ },
+ "role": {
+ "type": "string",
+ "description": "User's role in the system. Determines permissions.",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "employee"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active. Defaults to true.",
+ "default": true
+ }
+ },
+ "required": [
+ "first_name",
+ "last_name",
+ "email",
+ "role"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_user_details",
+ "title": null,
+ "description": "Update an existing user in the HR system with smart change detection. Only updates fields that have actually changed. Validates email uniqueness, name combination uniqueness, and role validity. User must exist in organization. Returns updated user details and list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "ID of the user to update (required). Must exist in the organization. Example: '1', '42'"
+ },
+ "email": {
+ "type": "string",
+ "description": "New email address (optional). Must be valid RFC-compliant email format and unique within organization. Invalid characters like *&^%#$ in email addresses are not allowed. Only provide if changing. Example: 'new.email@company.com'",
+ "format": "email",
+ "maxLength": 120
+ },
+ "first_name": {
+ "type": "string",
+ "description": "New first name (optional, 1-60 characters). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*() are not allowed. Only provide if changing. Example: 'NewFirstName', 'Mary-Jane'",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "last_name": {
+ "type": "string",
+ "description": "New last name (optional, 1-60 characters). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*() are not allowed. Only provide if changing. Example: 'NewLastName', 'O'Brien'",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "phone": {
+ "type": "string",
+ "description": "New phone number (optional, max 30 characters). Only provide if changing. Example: '+1-555-999-8888'",
+ "maxLength": 30
+ },
+ "role": {
+ "type": "string",
+ "description": "New role (optional). Only provide if changing. Valid values determine user permissions.",
+ "enum": [
+ "admin",
+ "agent",
+ "manager",
+ "employee"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Set to false to deactivate user. Only provide if changing."
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_user_groups",
+ "title": null,
+ "description": "List user groups with optional filtering by group_id, name, active status, or type. All groups are automatically scoped to the requester's organization. Supports multiple filters (AND logic).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "Filter by exact group ID. Example: 1"
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by exact name (case-sensitive). Example: 'IT Support'"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status. Example: true"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ],
+ "description": "Filter by group type"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_group_by_name",
+ "title": null,
+ "description": "Find a group by exact name (case-sensitive). Returns the group if found in the organization. Name must match exactly including case.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Group name to search for (exact match, case-sensitive). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Example: 'IT Support' will NOT match 'it support'",
+ "minLength": 1,
+ "maxLength": 80
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_group_members",
+ "title": null,
+ "description": "List all members of a specific group with optional filtering by member_id or user_id. Returns membership records.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "integer",
+ "description": "ID of the group to list members for (required). Example: 1, 42"
+ },
+ "member_id": {
+ "type": "integer",
+ "description": "Filter by exact member ID (optional). Example: 5"
+ },
+ "user_id": {
+ "type": "integer",
+ "description": "Filter by exact user ID (optional). Example: 10"
+ }
+ },
+ "required": [
+ "group_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_user_group",
+ "title": null,
+ "description": "Create a new user group in the HR system. Validates name uniqueness within organization and group type validity. Group is automatically assigned to the requester's organization. Returns complete group details including auto-generated ID and timestamps. Requires groups/crud permission.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Group name (1-80 characters, must be unique within organization). Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*()!~` are not permitted. Examples: 'IT Support Team', 'HR Service Desk', 'L1 Support'",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "type": {
+ "type": "string",
+ "description": "Group type - determines the group's purpose and capabilities",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the group is active. Defaults to true.",
+ "default": true
+ }
+ },
+ "required": [
+ "name",
+ "type"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_user_group",
+ "title": null,
+ "description": "Update an existing user group with smart change detection. Only updates fields that have actually changed. Validates name uniqueness and type validity. Group must exist in organization. Returns updated group details and list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "ID of the group to update (required). Must exist in the organization. Example: '1', '42'"
+ },
+ "name": {
+ "type": "string",
+ "description": "New group name (optional). Must be unique within organization. Only letters, spaces, hyphens (-), apostrophes ('), and periods (.) allowed. Special characters like @#$%^&*()!~` are not permitted. Only provide if changing. Example: 'Updated IT Support'",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "type": {
+ "type": "string",
+ "description": "New group type (optional). Only provide if changing.",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Set to false to deactivate group. Only provide if changing."
+ }
+ },
+ "required": [
+ "group_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_group_member",
+ "title": null,
+ "description": "Add a user to a group. Validates that both group and user exist in the same organization and that the user is not already a member. Returns the created membership details.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "ID of the group to add the user to. Example: '1', '42'"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "ID of the user to add to the group. Example: '5', '123'"
+ }
+ },
+ "required": [
+ "group_id",
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_group_membership",
+ "title": null,
+ "description": "Remove a user from a group. Requires only group_id and user_id since this pair uniquely identifies the membership. Validates that the user is currently a member of the group. Returns the removed membership details.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "ID of the group to remove the user from. Example: '1', '42'"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "ID of the user to remove from the group. Example: '5', '123'"
+ }
+ },
+ "required": [
+ "group_id",
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_hr_criteria",
+ "title": null,
+ "description": "Flexible search for HR criteria. At least ONE parameter must be provided. Search by ID, name, type, active status, user group, users, or creation dates. Returns HR criteria with type (case_visibility or approval), user_group, users array, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_criteria_id": {
+ "type": "string",
+ "description": "HR criteria ID for exact match (optional)"
+ },
+ "name": {
+ "type": "string",
+ "description": "HR criteria name for partial matching (optional)"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "case_visibility",
+ "approval"
+ ],
+ "description": "Filter by type: case_visibility or approval (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "user_group": {
+ "type": "string",
+ "description": "Filter by user group ID (optional)"
+ },
+ "users": {
+ "type": "string",
+ "description": "Filter by user IDs (comma-separated, e.g., '1,2,3'). Matches if any user ID exists in the criteria's users array (optional)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter by created before date. Use ISO format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS (optional)"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter by created after date. Use ISO format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "register_hr_criteria",
+ "title": null,
+ "description": "Register a new HR criteria with validation. Name must be unique within organization. User group and users must exist if provided. Returns created HR criteria with type (case_visibility or approval), user_group, users array, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Criteria name (must be unique within organization, required)"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "case_visibility",
+ "approval"
+ ],
+ "description": "Type: case_visibility or approval (required)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Active status (default: true, optional)"
+ },
+ "user_group": {
+ "type": "string",
+ "description": "User group ID (optional, must exist in organization)"
+ },
+ "users": {
+ "type": "string",
+ "description": "User IDs (comma-separated, e.g., '1,2,3') (optional, must exist in organization)"
+ }
+ },
+ "required": [
+ "name",
+ "type"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_hr_criteria",
+ "title": null,
+ "description": "Update an existing HR criteria with smart change detection. At least one field must be provided to update. Name must be unique within organization if changed. User group and users must exist if provided. Returns updated HR criteria and list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_criteria_id": {
+ "type": "string",
+ "description": "HR criteria ID to update (required, identifies the record)"
+ },
+ "name": {
+ "type": "string",
+ "description": "New criteria name (optional, must be unique within organization)"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "case_visibility",
+ "approval"
+ ],
+ "description": "New type: case_visibility or approval (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional)"
+ },
+ "user_group": {
+ "type": "string",
+ "description": "New user group ID (optional, must exist in organization)"
+ },
+ "users": {
+ "type": "string",
+ "description": "New user IDs (comma-separated, e.g., '1,2,3') (optional, must exist in organization)"
+ }
+ },
+ "required": [
+ "hr_criteria_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_skills",
+ "title": null,
+ "description": "Flexible search for skills. At least ONE parameter must be provided. Search by skill ID, name, active status, or creation dates. Returns skills with skill_id, name, active status, org_id, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "skill_id": {
+ "type": "string",
+ "description": "Skill ID for exact match (optional)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Skill name for partial matching (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter by created before date. Use ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS (optional)"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter by created after date. Use ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_user_skills",
+ "title": null,
+ "description": "Flexible search for user skills (skill-user assignments). At least ONE parameter must be provided. Search by user_skill_id, skill ID, user ID, or creation dates. Returns user skills with user_skill_id, skill, user, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_skill_id": {
+ "type": "string",
+ "description": "User skill ID for exact match (optional)"
+ },
+ "skill": {
+ "type": "string",
+ "description": "Filter by skill ID (optional)"
+ },
+ "user": {
+ "type": "string",
+ "description": "Filter by user ID (optional)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter by created before date. Use ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS (optional)"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter by created after date. Use ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_skill",
+ "title": null,
+ "description": "Add a new skill to the organization. Skill name must be unique within the organization. The 'active' field is optional and defaults to True if not provided. Returns the created skill with skill_id, name, active status, and timestamps.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Skill name (required, must be unique within organization)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Active status (optional)",
+ "default": true
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_skill",
+ "title": null,
+ "description": "Update an existing skill by skill_id. At least ONE field (name or active) must be provided for update. Smart change detection - only updates changed fields. Name must be unique within organization if changed. Returns updated skill with list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "skill_id": {
+ "type": "string",
+ "description": "Skill ID to update (required)"
+ },
+ "name": {
+ "type": "string",
+ "description": "New skill name (optional, must be unique if changed)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional)"
+ }
+ },
+ "required": [
+ "skill_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_skill_to_user",
+ "title": null,
+ "description": "Assign a skill to a user by creating a user_skill record. Both skill and user must exist in the organization. Returns the created assignment with enhanced details including skill_name, user_email, user_first_name, and user_last_name.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "skill": {
+ "type": "string",
+ "description": "Skill ID to assign (required, must exist in organization)"
+ },
+ "user": {
+ "type": "string",
+ "description": "User ID to assign skill to (required, must exist in organization)"
+ }
+ },
+ "required": [
+ "skill",
+ "user"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_user_skills",
+ "title": null,
+ "description": "Remove a user skill assignment (hard delete) by user_skill_id. Permanently deletes the skill-user assignment. Returns deleted assignment details including skill_name and user information.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_skill_id": {
+ "type": "string",
+ "description": "User skill ID to delete (required)"
+ }
+ },
+ "required": [
+ "user_skill_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_checklists",
+ "title": null,
+ "description": "Get checklists with flexible filtering options. Returns matching checklists with details including ID, description, checked status, and associated case task. All parameters are optional - returns all checklists if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "checklist_id": {
+ "type": "integer",
+ "description": "Filter by specific checklist ID (exact match, optional)"
+ },
+ "checklist_item_description": {
+ "type": "string",
+ "description": "Filter by description content (partial match, case-insensitive, optional)"
+ },
+ "checked": {
+ "type": "boolean",
+ "description": "Filter by checked status (exact match, optional)"
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "Filter by associated case task ID (exact match, optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_checklist",
+ "title": null,
+ "description": "Create a new checklist item with validation. Validates that the case task exists in the database. Returns the created checklist item with all details. Use this to add new checklist items to HR case tasks.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "checklist_item_description": {
+ "type": "string",
+ "description": "Description of the checklist item. Example: 'Submit identification documents', 'Complete training sessions'"
+ },
+ "checked": {
+ "type": "boolean",
+ "description": "Whether the item is checked/completed. Defaults to false if not provided.",
+ "default": false
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "ID of the associated case task (must exist in database). Example: 1"
+ }
+ },
+ "required": [
+ "checklist_item_description",
+ "case_task_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_checklist",
+ "title": null,
+ "description": "Update an existing checklist item with smart change detection. Validates all field changes and prevents unnecessary updates by detecting if fields are already set to the provided values. Updates only the fields provided and automatically sets the updated_at timestamp. Returns the updated checklist with changes made listed.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "checklist_id": {
+ "type": "integer",
+ "description": "ID of the checklist item to update (must exist in database). Example: 1"
+ },
+ "checklist_item_description": {
+ "type": "string",
+ "description": "New description of the checklist item. Optional - only provide if changing."
+ },
+ "checked": {
+ "type": "boolean",
+ "description": "New checked status. Optional - only provide if changing."
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "New associated case task ID (must exist in database). Optional - only provide if changing."
+ }
+ },
+ "required": [
+ "checklist_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_surveys",
+ "title": null,
+ "description": "Get surveys with flexible filtering options. Returns matching surveys with all question fields. All parameters are optional - returns all surveys if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "survey_id": {
+ "type": "integer",
+ "description": "Filter by specific survey ID (exact match, optional)"
+ },
+ "question_1": {
+ "type": "string",
+ "description": "Filter by question 1 content (partial match, case-insensitive, optional)"
+ },
+ "question_2": {
+ "type": "string",
+ "description": "Filter by question 2 content (partial match, case-insensitive, optional)"
+ },
+ "question_3": {
+ "type": "string",
+ "description": "Filter by question 3 content (partial match, case-insensitive, optional)"
+ },
+ "question_4": {
+ "type": "string",
+ "description": "Filter by question 4 content (partial match, case-insensitive, optional)"
+ },
+ "question_5": {
+ "type": "string",
+ "description": "Filter by question 5 content (partial match, case-insensitive, optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_survey",
+ "title": null,
+ "description": "Create a new survey with validation. At least one question must be provided. Returns the created survey with all fields and the assigned survey ID.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "question_1": {
+ "type": "string",
+ "description": "Question 1 text (optional)"
+ },
+ "question_2": {
+ "type": "string",
+ "description": "Question 2 text (optional)"
+ },
+ "question_3": {
+ "type": "string",
+ "description": "Question 3 text (optional)"
+ },
+ "question_4": {
+ "type": "string",
+ "description": "Question 4 text (optional)"
+ },
+ "question_5": {
+ "type": "string",
+ "description": "Question 5 text (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_survey",
+ "title": null,
+ "description": "Update an existing survey with smart change detection. Only provides questions you want to modify; others will remain unchanged. Returns the updated survey with all fields and a list of which fields were changed.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "survey_id": {
+ "type": "integer",
+ "description": "ID of the survey to update (required)"
+ },
+ "question_1": {
+ "type": "string",
+ "description": "New question 1 text (optional, provide only if changing)"
+ },
+ "question_2": {
+ "type": "string",
+ "description": "New question 2 text (optional, provide only if changing)"
+ },
+ "question_3": {
+ "type": "string",
+ "description": "New question 3 text (optional, provide only if changing)"
+ },
+ "question_4": {
+ "type": "string",
+ "description": "New question 4 text (optional, provide only if changing)"
+ },
+ "question_5": {
+ "type": "string",
+ "description": "New question 5 text (optional, provide only if changing)"
+ }
+ },
+ "required": [
+ "survey_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_survey_instances",
+ "title": null,
+ "description": "Get survey instances with flexible filtering options. Returns matching instances with details including responses to survey questions, assigned user, and other metadata. All parameters are optional - returns all survey instances if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "survey_instance_id": {
+ "type": "integer",
+ "description": "Filter by specific survey instance ID (exact match, optional)"
+ },
+ "survey_id": {
+ "type": "integer",
+ "description": "Filter by survey ID (exact match, optional)"
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "Filter by associated case task ID (exact match, optional)"
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "Filter by assigned user ID (exact match, optional)"
+ },
+ "answer_1": {
+ "type": "string",
+ "description": "Filter by answer 1 content (partial match, case-insensitive, optional)"
+ },
+ "answer_2": {
+ "type": "string",
+ "description": "Filter by answer 2 content (partial match, case-insensitive, optional)"
+ },
+ "answer_3": {
+ "type": "string",
+ "description": "Filter by answer 3 content (partial match, case-insensitive, optional)"
+ },
+ "answer_4": {
+ "type": "string",
+ "description": "Filter by answer 4 content (partial match, case-insensitive, optional)"
+ },
+ "answer_5": {
+ "type": "string",
+ "description": "Filter by answer 5 content (partial match, case-insensitive, optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_survey_instance",
+ "title": null,
+ "description": "Create a new survey instance with validation. Assigns a user to complete a survey, optionally linking it to a case task. Can include answers to survey questions or leave them blank for later completion.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "survey_id": {
+ "type": "integer",
+ "description": "ID of the survey this instance is for (required)"
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "ID of the associated case task (optional)"
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "ID of the user assigned to complete this survey (optional)"
+ },
+ "answer_1": {
+ "type": "string",
+ "description": "Answer for question 1 (optional)"
+ },
+ "answer_2": {
+ "type": "string",
+ "description": "Answer for question 2 (optional)"
+ },
+ "answer_3": {
+ "type": "string",
+ "description": "Answer for question 3 (optional)"
+ },
+ "answer_4": {
+ "type": "string",
+ "description": "Answer for question 4 (optional)"
+ },
+ "answer_5": {
+ "type": "string",
+ "description": "Answer for question 5 (optional)"
+ }
+ },
+ "required": [
+ "survey_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_survey_instance",
+ "title": null,
+ "description": "Update an existing survey instance with smart change detection. Can update assignment, associated case task, or survey responses. Only updates fields that are explicitly provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "survey_instance_id": {
+ "type": "integer",
+ "description": "ID of the survey instance to update (required)"
+ },
+ "survey_id": {
+ "type": "integer",
+ "description": "New ID of the survey this instance is for (optional)"
+ },
+ "case_task_id": {
+ "type": "integer",
+ "description": "New ID of the associated case task (optional)"
+ },
+ "assigned_to": {
+ "type": "integer",
+ "description": "New ID of the user assigned to complete this survey (optional)"
+ },
+ "answer_1": {
+ "type": "string",
+ "description": "New answer for question 1 (optional)"
+ },
+ "answer_2": {
+ "type": "string",
+ "description": "New answer for question 2 (optional)"
+ },
+ "answer_3": {
+ "type": "string",
+ "description": "New answer for question 3 (optional)"
+ },
+ "answer_4": {
+ "type": "string",
+ "description": "New answer for question 4 (optional)"
+ },
+ "answer_5": {
+ "type": "string",
+ "description": "New answer for question 5 (optional)"
+ }
+ },
+ "required": [
+ "survey_instance_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_hr_case_by_number",
+ "title": null,
+ "description": "Get complete HR case details by unique case number. Returns full case information including all related entities (HR service, profiles, user assignments, approval criteria). Use this to retrieve comprehensive case details for review, update, or reference.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "type": "string",
+ "description": "The unique case number to retrieve. Must match exactly the number column value in format HRC####### where ####### is a zero-padded 7-digit number. Examples: 'HRC0000001', 'HRC0000002', 'HRC0000770'",
+ "pattern": "^HRC\\d{7}$",
+ "minLength": 10,
+ "maxLength": 10
+ }
+ },
+ "required": [
+ "number"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_my_cases_to_approve",
+ "title": null,
+ "description": "Find all HR cases awaiting approval by a specific user. Returns cases where the user is listed as approver and request_status is 'requested'. Use this to get a user's approval queue or pending approvals workload. The Cases are returned based on the user token",
+ "inputSchema": {
+ "type": "object",
+ "properties": {},
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_hr_cases",
+ "title": null,
+ "description": "Search and filter HR cases by multiple criteria. Returns a list of matching cases with all related entities (HR services, profiles, users, groups, criteria) fully expanded. All parameters are optional - use any combination to filter results. Perfect for discovering cases, generating reports, or finding cases with specific characteristics.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_id": {
+ "type": "string",
+ "description": "Filter by specific case ID. Example: '1'"
+ },
+ "number": {
+ "type": "string",
+ "description": "Filter by case number (exact match). Must match exactly the number column value in format HRC####### where ####### is a zero-padded 7-digit number. Examples: 'HRC0000001', 'HRC0000002', 'HRC0000770'",
+ "pattern": "^HRC\\d{7}$",
+ "minLength": 10,
+ "maxLength": 10
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by case status",
+ "enum": [
+ "draft",
+ "ready",
+ "awaiting_approval",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "awaiting_acceptance",
+ "suspended",
+ "cancelled"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "Filter by HR service name"
+ },
+ "opened_for": {
+ "type": "string",
+ "description": "Filter by opened_for user name 'first_name last_name'"
+ },
+ "opened_by": {
+ "type": "string",
+ "description": "Filter by opened_by user name 'first_name last_name'"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Filter by priority level",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "source": {
+ "type": "string",
+ "description": "Filter by how the case was created",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name'"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group name (example: `IT Support`)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Filter by short description (partial match, case-insensitive). Example: 'payroll'"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Filter by worknotes content (partial match, case-insensitive). Example: 'urgent'"
+ },
+ "skills": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "Filter by required skill IDs. Example: [1, 2, 3]"
+ },
+ "approval_criteria": {
+ "type": "string",
+ "description": "Filter by approval criteria name"
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "Filter by Center of Excellence type",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "approver": {
+ "type": "string",
+ "description": "Filter by approver user name 'first_name last_name'"
+ },
+ "request_status": {
+ "type": "string",
+ "description": "Filter by approval request status",
+ "enum": [
+ "approved",
+ "rejected",
+ "requested"
+ ]
+ },
+ "account_number": {
+ "type": "string",
+ "description": "Filter by account number (partial match). Example: '1234'"
+ },
+ "account_type": {
+ "type": "string",
+ "description": "Filter by account type",
+ "enum": [
+ "checking",
+ "savings",
+ "other"
+ ]
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter cases created after this date (ISO format). Example: '2024-01-01T00:00:00Z'"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter cases created before this date (ISO format). Example: '2024-12-31T23:59:59Z'"
+ },
+ "limit": {
+ "type": "integer",
+ "description": "Maximum number of results to return (default: 50, max: 100)",
+ "default": 50,
+ "minimum": 1,
+ "maximum": 100
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_cases_assigned_to",
+ "title": null,
+ "description": "Find all HR cases assigned to a specific group or user. Returns cases matching the assignment criteria with all related entities expanded. Provide either assignment_group, assigned_to, or both. Use this to see a group's or individual's current caseload.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group name (optional, but one parameter required, example: `IT Support`)"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name' (optional, but one parameter required)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_new_hr_case",
+ "title": null,
+ "description": "Create a new HR case with complete validation. Validates that all referenced entities (hr_service, profiles, users, groups, criteria) exist in the database. Automatically generates a unique case number in format HRC#######. Returns the created case with all relationships fully expanded. Use this to initiate new HR service requests, incidents, or support cases.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "description": "Initial case status. Defaults to 'draft' if not provided.",
+ "enum": [
+ "draft",
+ "ready",
+ "awaiting_approval",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "awaiting_acceptance",
+ "suspended",
+ "cancelled"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "HR service ID this case relates to (must exist in database). Example: '5'. Optional."
+ },
+ "opened_for": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name' for person case is opened for. Optional."
+ },
+ "priority": {
+ "type": "string",
+ "description": "Case priority. Defaults to 'planning' if not provided.",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "source": {
+ "type": "string",
+ "description": "How the case was created. Optional.",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name'"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group name (example: `IT Support`)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Brief description of the case (required, max 120 characters). Example: 'Payroll correction needed for employee'"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Work notes for the case (max 120 characters). Optional."
+ },
+ "skills": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "Array of skill IDs required for the case. Example: [1, 2, 3]. Optional."
+ },
+ "approval_criteria": {
+ "type": "string",
+ "description": "HR criteria ID for approval rules (must exist). Example: '2'. Optional."
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "Center of Excellence type (required)",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "approver": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name' for the approver. Optional."
+ },
+ "request_status": {
+ "type": "string",
+ "description": "Approval request status. Optional.",
+ "enum": [
+ "approved",
+ "rejected",
+ "requested"
+ ]
+ },
+ "account_number": {
+ "type": "string",
+ "description": "Account number for payroll-related cases (optional, max 120 characters). Typically used for direct deposit setup or bank account changes. Example: '123456789'"
+ },
+ "account_type": {
+ "type": "string",
+ "description": "Account type for payroll. Optional.",
+ "enum": [
+ "checking",
+ "savings",
+ "other"
+ ]
+ }
+ },
+ "required": [
+ "short_description",
+ "coe_type"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_hr_case",
+ "title": null,
+ "description": "Update an existing HR case with smart change detection. Validates all field changes and prevents unnecessary updates by detecting if fields are already set to the provided values. Can update a single case by ID/number or batch update multiple cases with filters. Updates only the fields provided and automatically sets the updated_at timestamp. Returns the updated case(s) with all relationships fully expanded and a list of fields changed.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_id": {
+ "type": "string",
+ "description": "ID of the case to update (must exist in database). Example: '1'. Use for single case updates."
+ },
+ "number": {
+ "type": "string",
+ "description": "Case number for verification (exact match). Must match exactly the number column value in format HRC####### where ####### is a zero-padded 7-digit number. Examples: 'HRC0000001', 'HRC0000002', 'HRC0000770'. Optional.",
+ "pattern": "^HRC\\d{7}$",
+ "minLength": 10,
+ "maxLength": 10
+ },
+ "status": {
+ "type": "string",
+ "description": "New case status. Optional - only provide if changing.",
+ "enum": [
+ "draft",
+ "ready",
+ "awaiting_approval",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "awaiting_acceptance",
+ "suspended",
+ "cancelled"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "New HR service ID (must exist in database). Optional - only provide if changing."
+ },
+ "opened_for": {
+ "type": "string",
+ "description": "New opened_for user name (must exist and should be in format 'first_name last_name'). Optional - only provide if changing."
+ },
+ "priority": {
+ "type": "string",
+ "description": "New priority level. Optional - only provide if changing.",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "source": {
+ "type": "string",
+ "description": "New source. Optional - only provide if changing.",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name' (must exist). Optional - only provide if changing."
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group name (example: `IT Support`)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "New short description (max 120 characters). Optional - only provide if changing."
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "New work notes (max 120 characters). Optional - only provide if changing."
+ },
+ "skills": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "New array of skill IDs. Optional - only provide if changing."
+ },
+ "approval_criteria": {
+ "type": "string",
+ "description": "New approval criteria ID (must exist). Optional - only provide if changing."
+ },
+ "coe_type": {
+ "type": "string",
+ "description": "New COE type. Optional - only provide if changing.",
+ "enum": [
+ "HRIT",
+ "Payroll",
+ "Talent Management",
+ "Total Rewards",
+ "Workforce Administration"
+ ]
+ },
+ "approver": {
+ "type": "string",
+ "description": "User name in format 'first_name last_name' (must exist). Optional - only provide if changing."
+ },
+ "request_status": {
+ "type": "string",
+ "description": "New request status. Optional - only provide if changing.",
+ "enum": [
+ "approved",
+ "rejected",
+ "requested"
+ ]
+ },
+ "account_number": {
+ "type": "string",
+ "description": "New account number (max 120 characters). Optional - only provide if changing."
+ },
+ "account_type": {
+ "type": "string",
+ "description": "New account type. Optional - only provide if changing.",
+ "enum": [
+ "checking",
+ "savings",
+ "other"
+ ]
+ },
+ "created_before": {
+ "type": "string",
+ "description": "For batch updates: update cases created before this date (ISO format). Example: '2024-12-31T23:59:59Z'"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "For batch updates: update cases created after this date (ISO format). Example: '2024-01-01T00:00:00Z'"
+ }
+ },
+ "required": [
+ "hr_case_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "onboard_new_hr_profile",
+ "title": null,
+ "description": "Create a new HR profile for a user. Auto-generates profile number (HR-001, HR-002, etc.). Validates user exists, doesn't have existing profile, and all uniqueness constraints (personal_email, national_tax_id). Establishes 1:1 relationship with User.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "ID of user to create profile for (must exist in organization and not have existing profile). Example: '1', '5'"
+ },
+ "personal_email": {
+ "type": "string",
+ "description": "Personal email address (must be unique within organization). Example: 'john.doe.personal@gmail.com'"
+ },
+ "national_tax_id": {
+ "type": "string",
+ "description": "National tax ID - provide 3-digit number (e.g., '123'). Will be auto-formatted as TAX-{org_id}-{input}. Example: '123', '456'"
+ },
+ "gender": {
+ "type": "string",
+ "description": "Gender (optional)",
+ "enum": [
+ "Male",
+ "Female",
+ "Other"
+ ]
+ },
+ "marital_status": {
+ "type": "string",
+ "description": "Marital status (optional)",
+ "enum": [
+ "Single",
+ "Married",
+ "Divorced"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Employment type (optional)",
+ "enum": [
+ "full-time",
+ "part-time",
+ "contractor"
+ ]
+ },
+ "dob": {
+ "type": "string",
+ "description": "Date of birth in ISO format: YYYY-MM-DD (optional). Example: '1990-01-15'"
+ },
+ "nationality": {
+ "type": "string",
+ "description": "Nationality code (optional)",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "employment_start_date": {
+ "type": "string",
+ "description": "Employment start date in ISO format: YYYY-MM-DD (optional). Example: '2024-01-01'"
+ },
+ "employment_end_date": {
+ "type": "string",
+ "description": "Employment end date in ISO format: YYYY-MM-DD (optional). Example: '2025-12-31'"
+ },
+ "manager": {
+ "type": "string",
+ "description": "Manager's hr_profile_id. User must have 'manager' role (must exist in same organization) (optional). Example: '1', '5'"
+ },
+ "location_type": {
+ "type": "string",
+ "description": "Work location type (optional)",
+ "enum": [
+ "Hotdesk",
+ "Office Based",
+ "Remote"
+ ]
+ },
+ "position": {
+ "type": "string",
+ "description": "Job position (optional)",
+ "enum": [
+ "Software Engineer",
+ "QA",
+ "Manager",
+ "HR",
+ "IT Support",
+ "Administration",
+ "Sales"
+ ]
+ }
+ },
+ "required": [
+ "user_id",
+ "personal_email",
+ "national_tax_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_hr_profile",
+ "title": null,
+ "description": "Update an existing HR profile with smart change detection. Can identify profile by hr_profile_id, number, personal_email, or user_id. Only updates fields that have changed. Returns list of changes made.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_profile_id": {
+ "type": "string",
+ "description": "HR Profile ID to update (optional identifier). Example: '1', '42'"
+ },
+ "number": {
+ "type": "string",
+ "description": "Profile number to update (optional identifier). Example: 'HR-001', 'HR-042'"
+ },
+ "personal_email": {
+ "type": "string",
+ "description": "Personal email to identify profile (optional identifier, can also be updated). Example: 'john.doe@gmail.com'"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "User ID to identify profile (optional identifier). Example: '1', '5'"
+ },
+ "gender": {
+ "type": "string",
+ "description": "New gender (optional)",
+ "enum": [
+ "Male",
+ "Female",
+ "Other"
+ ]
+ },
+ "marital_status": {
+ "type": "string",
+ "description": "New marital status (optional)",
+ "enum": [
+ "Single",
+ "Married",
+ "Divorced"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "New employment type (optional)",
+ "enum": [
+ "full-time",
+ "part-time",
+ "contractor"
+ ]
+ },
+ "dob": {
+ "type": "string",
+ "description": "New date of birth in ISO format: YYYY-MM-DD (optional). Example: '1990-01-15'"
+ },
+ "nationality": {
+ "type": "string",
+ "description": "New nationality code (optional)",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "employment_start_date": {
+ "type": "string",
+ "description": "New employment start date in ISO format: YYYY-MM-DD (optional). Example: '2024-06-01'"
+ },
+ "employment_end_date": {
+ "type": "string",
+ "description": "New employment end date in ISO format: YYYY-MM-DD (optional). Example: '2026-12-31'"
+ },
+ "manager": {
+ "type": "string",
+ "description": "New manager's hr_profile_id. User must have 'manager' role (must exist in same organization, cannot be self) (optional). Example: '2', '10'"
+ },
+ "location_type": {
+ "type": "string",
+ "description": "New work location type (optional)",
+ "enum": [
+ "Hotdesk",
+ "Office Based",
+ "Remote"
+ ]
+ },
+ "position": {
+ "type": "string",
+ "description": "New job position (optional)",
+ "enum": [
+ "Software Engineer",
+ "QA",
+ "Manager",
+ "HR",
+ "IT Support",
+ "Administration",
+ "Sales"
+ ]
+ },
+ "national_tax_id": {
+ "type": "string",
+ "description": "New national tax ID - provide 3-digit number (e.g., '123'). Will be auto-formatted as TAX-{org_id}-{input} (must be unique within organization) (optional). Example: '456', '789'"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "offboard_hr_profile",
+ "title": null,
+ "description": "Offboard a single HR profile by setting employment_end_date to today. Can identify by hr_profile_id, number, personal_email, or user_id. Idempotent operation - can be called multiple times safely.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_profile_id": {
+ "type": "string",
+ "description": "HR Profile ID to offboard (optional identifier). Example: '1', '5'"
+ },
+ "number": {
+ "type": "string",
+ "description": "Profile number to offboard (optional identifier). Example: 'HR-001', 'HR-005'"
+ },
+ "personal_email": {
+ "type": "string",
+ "description": "Personal email to identify profile (optional identifier). Example: 'john.doe@gmail.com'"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "User ID to identify profile (optional identifier). Example: '1', '5'"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "offboard_hr_profiles",
+ "title": null,
+ "description": "Bulk offboard HR profiles matching filter criteria. Sets employment_end_date to today for all matching profiles. Returns count and list of offboarded profiles. All filters are optional and combined with AND logic. Note: 1) If you include yourself in the filter, it silently avoids self-offboarding. 2) Already offboarded profiles are automatically skipped - only active profiles will be offboarded.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_profile_id": {
+ "type": "string",
+ "description": "Filter by HR Profile ID"
+ },
+ "number": {
+ "type": "string",
+ "description": "Filter by profile number. Example: 'HR-001'"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "Filter by user ID"
+ },
+ "personal_email": {
+ "type": "string",
+ "description": "Filter by personal email"
+ },
+ "gender": {
+ "type": "string",
+ "description": "Filter by gender",
+ "enum": [
+ "Male",
+ "Female",
+ "Other"
+ ]
+ },
+ "marital_status": {
+ "type": "string",
+ "description": "Filter by marital status",
+ "enum": [
+ "Single",
+ "Married",
+ "Divorced"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Filter by employment type. Example: offboard all contractors",
+ "enum": [
+ "full-time",
+ "part-time",
+ "contractor"
+ ]
+ },
+ "dob": {
+ "type": "string",
+ "description": "Filter by date of birth (ISO format: YYYY-MM-DD)"
+ },
+ "nationality": {
+ "type": "string",
+ "description": "Filter by nationality",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "employment_start_date": {
+ "type": "string",
+ "description": "Filter by employment start date (ISO format)"
+ },
+ "employment_end_date": {
+ "type": "string",
+ "description": "Filter by employment end date (ISO format). Use null to exclude already-offboarded"
+ },
+ "manager": {
+ "type": "string",
+ "description": "Filter by manager hr_profile_id. Example: offboard all employees under manager 1"
+ },
+ "location_type": {
+ "type": "string",
+ "description": "Filter by location type",
+ "enum": [
+ "Hotdesk",
+ "Office Based",
+ "Remote"
+ ]
+ },
+ "national_tax_id": {
+ "type": "string",
+ "description": "Filter by national tax ID"
+ },
+ "position": {
+ "type": "string",
+ "description": "Filter by position. Example: offboard all QA",
+ "enum": [
+ "Software Engineer",
+ "QA",
+ "Manager",
+ "HR",
+ "IT Support",
+ "Administration",
+ "Sales"
+ ]
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter profiles created before this date (ISO format: YYYY-MM-DD). Example: '2024-01-01'"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter profiles created after this date (ISO format: YYYY-MM-DD). Example: '2023-01-01'"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_hr_profile_by_id",
+ "title": null,
+ "description": "Get HR profile by its primary key ID (hr_profile_id). Direct lookup by database ID. Returns complete profile details.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_profile_id": {
+ "type": "string",
+ "description": "The unique hr_profile_id primary key. Example: '1', '42'"
+ }
+ },
+ "required": [
+ "hr_profile_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_hr_profile_by_personal_email",
+ "title": null,
+ "description": "Get HR profile by personal email address (case-insensitive lookup). Returns complete profile details if email exists.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "personal_email": {
+ "type": "string",
+ "description": "Personal email address to search. Case-insensitive. Example: 'john.doe@gmail.com'"
+ }
+ },
+ "required": [
+ "personal_email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_users_hr_profile",
+ "title": null,
+ "description": "Get HR profile by user_id (uses 1:1 relationship between User and HRProfile). Returns the user's HR profile if it exists.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "The user's ID to get profile for. Example: '1', '5'"
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "fetch_hr_profile_by_number",
+ "title": null,
+ "description": "Get a single HR profile by its profile number (e.g., HR-001, HR-042). Returns complete profile details including employment dates, manager, and all attributes.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "type": "string",
+ "description": "Profile number to retrieve. Example: 'HR-001', 'HR-042'"
+ }
+ },
+ "required": [
+ "number"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "fetch_hr_profiles",
+ "title": null,
+ "description": "Search/list HR profiles with flexible filtering. All filters are optional and combined with AND logic. Returns list of matching profiles. Useful for finding employees by department, role, status, manager, etc.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "gender": {
+ "type": "string",
+ "description": "Filter by gender",
+ "enum": [
+ "Male",
+ "Female",
+ "Other"
+ ]
+ },
+ "marital_status": {
+ "type": "string",
+ "description": "Filter by marital status",
+ "enum": [
+ "Single",
+ "Married",
+ "Divorced"
+ ]
+ },
+ "type": {
+ "type": "string",
+ "description": "Filter by employment type. Example: find all contractors",
+ "enum": [
+ "full-time",
+ "part-time",
+ "contractor"
+ ]
+ },
+ "dob": {
+ "type": "string",
+ "description": "Filter by date of birth (ISO format: YYYY-MM-DD)"
+ },
+ "nationality": {
+ "type": "string",
+ "description": "Filter by nationality code",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "employment_start_date": {
+ "type": "string",
+ "description": "Filter by employment start date (ISO format: YYYY-MM-DD)"
+ },
+ "employment_end_date": {
+ "type": "string",
+ "description": "Filter by employment end date (ISO format: YYYY-MM-DD). Use 'null' to find active employees only"
+ },
+ "manager": {
+ "type": "string",
+ "description": "Filter by manager's hr_profile_id. Example: find all employees under manager 1"
+ },
+ "location_type": {
+ "type": "string",
+ "description": "Filter by work location type",
+ "enum": [
+ "Hotdesk",
+ "Office Based",
+ "Remote"
+ ]
+ },
+ "national_tax_id": {
+ "type": "string",
+ "description": "Filter by national tax ID"
+ },
+ "position": {
+ "type": "string",
+ "description": "Filter by job position. Example: find all Software Engineers",
+ "enum": [
+ "Software Engineer",
+ "QA",
+ "Manager",
+ "HR",
+ "IT Support",
+ "Administration",
+ "Sales"
+ ]
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "retrieve_knowledge_articles",
+ "title": null,
+ "description": "Retrieve knowledge articles with optional filters, scoped to user's organization.\n \n Use this tool to retrieve a list of knowledge articles. Without filters, returns all articles in the organization.\n With filters, returns only articles matching the specified criteria.\n \n Optional Filters:\n - knowledge_id: Filter by knowledge ID (exact match)\n - kb_number: Filter by KB number (exact match)\n - title: Filter by title (partial match, case-insensitive)\n - body: Filter by body content (partial match, case-insensitive)\n - state: Filter by state (draft, published, retired)\n - visibility: Filter by visibility (internal, external)\n - owner_id: Filter by owner user ID\n - created_before: Filter articles created before date (ISO 8601 format: 2024-01-15 or 2024-01-15T09:00:00)\n - created_after: Filter articles created after date (ISO 8601 format)\n \n Returns a list of knowledge article objects matching the filters, or all articles if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by knowledge ID (exact match)"
+ },
+ "kb_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by KB number (exact match)"
+ },
+ "title": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by title (partial match, case-insensitive)"
+ },
+ "body": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by body content (partial match, case-insensitive)"
+ },
+ "state": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by state",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ]
+ },
+ "visibility": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by visibility",
+ "enum": [
+ "internal",
+ "external"
+ ]
+ },
+ "owner_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by owner user ID"
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter articles created before this date (ISO 8601 format)"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter articles created after this date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_knowledge_article",
+ "title": null,
+ "description": "Create a new knowledge article in the system.\n \n Use this tool to add a new knowledge article. The system automatically generates kb_number \n (KB-001, KB-002, etc.) if not provided. KB numbers are unique within an organization.\n \n Required Parameters:\n - title: Article title (1-120 characters)\n \n Optional Parameters:\n - body: Article body content\n - state: Article state (draft, published, retired) - defaults to published\n - visibility: Article visibility (internal, external) - defaults to internal\n - owner_id: Owner user ID (must belong to same organization)\n \n Auto-Generated Fields:\n - kb_number: KB number (KB-001, KB-002, etc.) if not provided\n - knowledge_id: Auto-incremented ID\n - created_at and updated_at timestamps\n \n Returns the newly created knowledge article object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Article title (required, 1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "body": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Article body content"
+ },
+ "state": {
+ "type": "string",
+ "description": "Article state (defaults to 'published')",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ],
+ "default": "published"
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Article visibility (defaults to 'internal')",
+ "enum": [
+ "internal",
+ "external"
+ ],
+ "default": "internal"
+ },
+ "owner_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Owner user ID (must belong to same organization)"
+ }
+ },
+ "required": [
+ "title"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_knowledge_article",
+ "title": null,
+ "description": "Update specific fields of an existing knowledge article.\n \n Use this tool to update one or more fields of a knowledge article identified by knowledge_id or kb_number.\n At least one field (besides identifiers) must be provided. The tool validates that the new values \n are different from current values (idempotency check).\n \n Required Parameter (one of):\n - knowledge_id: Knowledge article ID\n - kb_number: KB number\n \n Optional Parameters (at least one required):\n - title: Updated article title (1-120 characters)\n - body: Updated article body content\n - state: Updated article state (draft, published, retired)\n - visibility: Updated article visibility (internal, external)\n - owner_id: Updated owner user ID (must belong to same organization)\n \n Note: Updating a field to its current value will result in an error (no changes detected).\n \n Returns the updated knowledge article object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Knowledge article ID (alternative to kb_number)"
+ },
+ "kb_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "KB number (alternative to knowledge_id)"
+ },
+ "title": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated article title (1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "body": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated article body content"
+ },
+ "state": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated article state",
+ "enum": [
+ "draft",
+ "published",
+ "retired"
+ ]
+ },
+ "visibility": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated article visibility",
+ "enum": [
+ "internal",
+ "external"
+ ]
+ },
+ "owner_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Updated owner user ID (must belong to same organization)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "link_knowledge_to_hr_case",
+ "title": null,
+ "description": "Link a knowledge article to an HR case.\n \n Use this tool to associate a knowledge article with an HR case. The link specifies how \n the knowledge article is used (suggested, applied, or as resolution).\n \n Required Parameters:\n - hr_case_id: HR case ID\n - knowledge_id: Knowledge article ID\n \n Optional Parameters:\n - used_as: Usage type (suggested, applied, resolution) - defaults to suggested\n \n Both HR case and knowledge article must belong to the same organization.\n A knowledge article can only be linked once to the same HR case.\n \n Returns the created link object.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_id": {
+ "type": "integer",
+ "description": "HR case ID (required)"
+ },
+ "knowledge_id": {
+ "type": "integer",
+ "description": "Knowledge article ID (required)"
+ },
+ "used_as": {
+ "type": "string",
+ "description": "Usage type (defaults to 'suggested')",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ],
+ "default": "suggested"
+ }
+ },
+ "required": [
+ "hr_case_id",
+ "knowledge_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_hr_case_knowledge_links",
+ "title": null,
+ "description": "Find HR case knowledge links with optional filters, scoped to user's organization.\n \n Use this tool to retrieve links between HR cases and knowledge articles. Without filters, \n returns all links in the organization. With filters, returns only links matching the criteria.\n \n Optional Filters:\n - hr_case_kb_id: Filter by link ID (exact match)\n - hr_case_id: Filter by HR case ID (exact match)\n - knowledge_id: Filter by knowledge ID (exact match)\n - used_as: Filter by usage type (suggested, applied, resolution)\n \n Returns a list of link objects matching the filters, or all links if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_kb_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by link ID (exact match)"
+ },
+ "hr_case_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by HR case ID (exact match)"
+ },
+ "knowledge_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by knowledge ID (exact match)"
+ },
+ "used_as": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by usage type",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ]
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_knowledge_link_to_hr_case",
+ "title": null,
+ "description": "Remove knowledge link(s) from HR case(s), scoped to user's organization.\n \n Use this tool to remove links between knowledge articles and HR cases. You can remove:\n - A specific link by its ID (hr_case_kb_id)\n - A specific link by case and knowledge (hr_case_id + knowledge_id)\n - All links for a specific case (hr_case_id only)\n \n Required Parameter (one of):\n - hr_case_kb_id: Specific link ID (takes precedence)\n - hr_case_id + knowledge_id: Specific link by case and knowledge\n - hr_case_id: All links for this case\n \n Returns the number of links removed.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_kb_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Specific link ID (takes precedence over other filters)"
+ },
+ "hr_case_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "HR case ID (required if hr_case_kb_id not provided)"
+ },
+ "knowledge_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Knowledge article ID (required if hr_case_kb_id not provided and hr_case_id provided)"
+ },
+ "used_as": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by usage type (not used for deletion, kept for compatibility)",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ]
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_assignment_rules",
+ "title": null,
+ "description": "Search and list assignment rules with flexible filtering. At least one search parameter must be provided. Supports filtering by ID, name (partial match), skills (ANY match), country, priority, active status, user group, and users (ANY match). All filters combined with AND logic.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_rule_id": {
+ "type": "integer",
+ "description": "Filter by exact assignment rule ID. Example: 1"
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by name (partial match, case-insensitive). Example: 'IT Support'"
+ },
+ "based_on_skills": {
+ "type": "string",
+ "description": "Filter by skill IDs (comma-separated). Matches if ANY skill is in rule's skills. Example: '1,2,3'"
+ },
+ "based_on_country": {
+ "type": "string",
+ "description": "Filter by country code. Valid values: US, GB, CA, IN, DE, FR, JP, CN, AU, BR. Example: 'US'",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "based_on_priority": {
+ "type": "string",
+ "description": "Filter by priority level. Valid values: critical, high, moderate, low, planning. Example: 'high'",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status. Example: true"
+ },
+ "user_group": {
+ "type": "integer",
+ "description": "Filter by user group ID. Example: 5"
+ },
+ "users": {
+ "type": "string",
+ "description": "Filter by user IDs (comma-separated). Matches if ANY user is in rule's users. Example: '10,11,12'"
+ },
+ "limit": {
+ "type": "integer",
+ "description": "Maximum results to return (default: 50, max: 100). Example: 20",
+ "default": 50,
+ "minimum": 1,
+ "maximum": 100
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_assignment_rule",
+ "title": null,
+ "description": "Create a new assignment rule with validation. Assignment rules define how HR cases are automatically routed to teams or individuals based on skills, country, priority, etc. The rule name must be unique within the organization. Skills, users, and user groups are validated against the database.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Assignment rule name (required, 1-120 characters, unique within organization). Example: 'IT Support Rules'",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "based_on_skills": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "List of skill IDs that trigger this rule (optional, validated). Example: [1, 2, 3]"
+ },
+ "based_on_country": {
+ "type": "string",
+ "description": "Country code that triggers this rule (optional). Valid values: US, GB, CA, IN, DE, FR, JP, CN, AU, BR. Example: 'US'",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "based_on_priority": {
+ "type": "string",
+ "description": "Priority level that triggers this rule (optional, defaults to 'planning'). Valid values: critical, high, moderate, low, planning. Example: 'high'",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ],
+ "default": "planning"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the rule is active (default: False). Inactive rules are not applied. Example: true",
+ "default": false
+ },
+ "user_group": {
+ "type": "integer",
+ "description": "User group ID to assign cases to (optional, must exist in organization). Example: 5"
+ },
+ "users": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "List of user IDs to assign cases to (optional, validated). Example: [10, 11, 12]"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_assignment_rules",
+ "title": null,
+ "description": "Update an existing assignment rule with smart change detection. Only updates fields that have actually changed. Returns the updated rule and a list of changes made. Skills, users, and user groups are validated if provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_rule_id": {
+ "type": "integer",
+ "description": "ID of the assignment rule to update (required). Must exist in organization. Example: 1"
+ },
+ "name": {
+ "type": "string",
+ "description": "New rule name (optional, 1-120 characters, must be unique if changed). Example: 'Updated IT Support Rules'",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "based_on_skills": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "New list of skill IDs (optional, replaces existing, validated). Example: [1, 2, 3, 4]"
+ },
+ "based_on_country": {
+ "type": "string",
+ "description": "New country code (optional). Valid values: US, GB, CA, IN, DE, FR, JP, CN, AU, BR. Example: 'GB'",
+ "enum": [
+ "US",
+ "GB",
+ "CA",
+ "IN",
+ "DE",
+ "FR",
+ "JP",
+ "CN",
+ "AU",
+ "BR"
+ ]
+ },
+ "based_on_priority": {
+ "type": "string",
+ "description": "New priority level (optional). Valid values: critical, high, moderate, low, planning. Example: 'critical'",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Example: true"
+ },
+ "user_group": {
+ "type": "integer",
+ "description": "New user group ID (optional, must exist if provided). Example: 6"
+ },
+ "users": {
+ "type": "array",
+ "items": {
+ "type": "integer"
+ },
+ "description": "New list of user IDs (optional, replaces existing, validated). Example: [10, 11, 12, 13]"
+ }
+ },
+ "required": [
+ "assignment_rule_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_escalation_rules",
+ "title": null,
+ "description": "Flexible search for escalation rules. At least ONE parameter must be provided. Search by escalation_rule_id, escalate_from (source group ID), or escalate_to (target group ID). Returns escalation rules with escalation_rule_id, escalate_from, escalate_to, org_id, escalate_from_group_name, and escalate_to_group_name for easy reference.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "escalation_rule_id": {
+ "type": "string",
+ "description": "Escalation rule ID for exact match (optional)"
+ },
+ "escalate_from": {
+ "type": "string",
+ "description": "Filter by source group ID (optional)"
+ },
+ "escalate_to": {
+ "type": "string",
+ "description": "Filter by target group ID (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_escalation_rule",
+ "title": null,
+ "description": "Add a new escalation rule by specifying source group (escalate_from) and target group (escalate_to). Both groups must exist in the organization. Returns the created escalation rule with escalation_rule_id, escalate_from, escalate_to, escalate_from_group_name, escalate_to_group_name, created_at timestamp, and org_id.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "escalate_from": {
+ "type": "string",
+ "description": "Source group ID (required, must exist in organization)"
+ },
+ "escalate_to": {
+ "type": "string",
+ "description": "Target group ID (required, must exist in organization)"
+ }
+ },
+ "required": [
+ "escalate_from",
+ "escalate_to"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_escalation_rule",
+ "title": null,
+ "description": "Remove an escalation rule by its ID. Returns the removed rule details including escalation_rule_id, escalate_from, escalate_to, group names, and org_id.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "escalation_rule_id": {
+ "type": "string",
+ "description": "Escalation rule ID to remove (required)"
+ }
+ },
+ "required": [
+ "escalation_rule_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_count_of_case_priority_wise",
+ "title": null,
+ "description": "Get count of cases grouped by priority, scoped to user's organization.\n \n Returns an object with priority as the key and the count of cases which has that priority value as the value.\n Example: {'critical': 5, 'high': 3, 'low': 2}\n \n Optional parameter:\n - priority_list: List of priorities to filter. If provided, only those priorities are considered for output.\n Valid priorities: critical, high, moderate, low, planning (all lowercase, case-sensitive).\n \n If a priority list is given, the output will only include those priorities (with count 0 if not found).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority_list": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of priorities to filter (critical, high, moderate, low, planning)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_case_for_assignment_group",
+ "title": null,
+ "description": "Count cases assigned to an assignment group with optional filters, scoped to user's organization.\n \n Returns an object where assignment_group_id is the key and the number of cases assigned to it is the count value.\n Example: {'assignment_group_id': 1, 'count': 5}\n \n Required parameter:\n - assignment_group_id: Assignment group ID\n \n Optional parameters (for filtering):\n - statuses: List of case statuses to filter. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled (all lowercase, case-sensitive)\n - priority_list: List of priorities to filter. Valid priorities: critical, high, moderate, low, planning (all lowercase, case-sensitive)\n - source: Source to filter. Valid sources: self-service, phone, email, chat, walk-in, virtual-agent (all lowercase, case-sensitive)\n \n All filters are applied with AND logic.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID (required)"
+ },
+ "statuses": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of case statuses to filter"
+ },
+ "priority_list": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of priorities to filter"
+ },
+ "source": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional source to filter"
+ }
+ },
+ "required": [
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_case_task_for_assignment_group",
+ "title": null,
+ "description": "Count case tasks assigned to an assignment group with optional status filter, scoped to user's organization.\n \n Returns an object where assignment_group_id is the key and the number of case tasks assigned to it is the count value.\n Example: {'assignment_group_id': 1, 'count': 3}\n \n Required parameter:\n - assignment_group_id: Assignment group ID\n \n Optional parameters (for filtering):\n - statuses: List of task statuses to filter. Valid statuses: draft, ready, work_in_progress, closed_complete, closed_incomplete, cancelled (all lowercase, case-sensitive)\n \n All filters are applied with AND logic.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "integer",
+ "description": "Assignment group ID (required)"
+ },
+ "statuses": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of task statuses to filter"
+ }
+ },
+ "required": [
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_status",
+ "title": null,
+ "description": "Count notifications grouped by status, scoped to user's organization.\n \n Returns status-wise notifications count as an object with status as key and count as value.\n Example: {'draft': 5, 'ready': 3, 'work_in_progress': 2}\n \n Optional parameter:\n - status: List of statuses to filter. If provided, only those statuses are considered for output.\n Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled (lowercase, case-sensitive).\n If a status list is given, the output will only include those statuses (with count 0 if not found).\n If not provided or null, returns counts for all statuses.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of statuses to filter. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_case",
+ "title": null,
+ "description": "Count notifications for cases, scoped to user's organization.\n \n Returns the total count of notifications.\n If case_ids are provided, counts notifications for those specific cases only.\n If case_ids are not provided, counts all notifications in the organization.\n \n Optional parameter:\n - case_ids: List of case IDs to filter (if not provided, counts all notifications)",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_ids": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "integer"
+ },
+ "description": "Optional list of case IDs to filter"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "avg_notifications_by_case",
+ "title": null,
+ "description": "Calculate average number of notifications per case, scoped to user's organization.\n \n Returns the average notifications count by cases as a float.\n Example: 2.5 (meaning on average each case has 2.5 notifications)\n \n Optional parameter:\n - case_ids: List of case IDs to filter (if not provided, calculates for all cases in organization)\n \n Note: If no cases exist, returns 0.0",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "case_ids": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "integer"
+ },
+ "description": "Optional list of case IDs to filter"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_type",
+ "title": null,
+ "description": "Count notifications grouped by type, scoped to user's organization.\n \n Returns type-wise notification count as an object with type as key and count as value.\n Example: {'report': 5, 'update': 3, 'alert': 2}\n \n Optional parameter:\n - type: List of notification types to filter. If provided, only those types are considered for output.\n Valid types: report, update, alert, reminder, solution_proposal, other (case-sensitive, lowercase).\n \n If a type list is given, the output will only include those types (with count 0 if not found).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional list of notification types to filter. Valid types: report, update, alert, reminder, solution_proposal, other"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications_for_email",
+ "title": null,
+ "description": "Find notifications for a specific email address, scoped to user's organization.\n \n Returns a list of notifications sent to the specified email address.\n \n Required parameter:\n - email: Email address to filter by (exact match)\n \n All notifications are scoped to the user's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Email address to filter by (required)"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications_sent_for_incident",
+ "title": null,
+ "description": "Find notifications sent for a specific HR case, scoped to user's organization.\n \n Returns a list of notifications sent for the specified HR case.\n \n Required parameter:\n - hr_case_id: HR case ID to filter by (exact match)\n \n All notifications are scoped to the user's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_id": {
+ "type": "integer",
+ "description": "HR case ID to filter by (required)"
+ }
+ },
+ "required": [
+ "hr_case_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications",
+ "title": null,
+ "description": "Find notifications with optional filters, scoped to user's organization.\n \n Returns a list of notifications matching all provided filters (AND logic).\n \n Optional filters:\n - notification_id: Exact match on notification ID\n - hr_case_id: Exact match on HR case ID\n - email: Exact match on email address\n - type: Exact match on notification type. Valid types: report, update, alert, reminder, solution_proposal, other (all lowercase, case-sensitive)\n - status: Exact match on notification status. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled (all lowercase, case-sensitive)\n - sys_created_on: Exact match on created date/time (ISO 8601 format, e.g., '2024-01-15' or '2024-01-15T09:00:00')\n \n All notifications are scoped to the user's organization.\n If no filters are provided, returns all notifications for the user's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by notification ID (exact match)"
+ },
+ "hr_case_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by HR case ID (exact match)"
+ },
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by email address (exact match)"
+ },
+ "type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification type (report, update, alert, reminder, solution_proposal, other)"
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification status (draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled)"
+ },
+ "sys_created_on": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by created date/time (ISO 8601 format, exact match, e.g., '2024-01-15' or '2024-01-15T09:00:00')"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "send_notification",
+ "title": null,
+ "description": "Send a new notification, scoped to user's organization.\n \n Creates a new notification for the specified HR case and email address.\n \n Required parameters:\n - hr_case_id: HR case ID (must belong to user's organization)\n - email: Recipient email address (must belong to a user in the same organization)\n \n Optional parameters:\n - type: Notification type. Valid types: report, update, alert, reminder, solution_proposal, other (default: other). All lowercase, case-sensitive.\n - status: Notification status. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled. All lowercase, case-sensitive.\n \n Example payload:\n {\n \"hr_case_id\": 1,\n \"email\": \"user@example.com\",\n \"type\": \"alert\",\n \"status\": \"ready\"\n }",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_id": {
+ "type": "integer",
+ "description": "HR case ID (required)"
+ },
+ "email": {
+ "type": "string",
+ "description": "Recipient email address (required)"
+ },
+ "type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Notification type (report, update, alert, reminder, solution_proposal, other). Default: other"
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Notification status (draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled)"
+ }
+ },
+ "required": [
+ "hr_case_id",
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_notification",
+ "title": null,
+ "description": "Update an existing notification, scoped to user's organization.\n \n Updates one or more fields of an existing notification.\n \n Required parameter:\n - notification_id: Notification ID to update\n \n Optional parameters (at least one required):\n - hr_case_id: Updated HR case ID (must belong to user's organization)\n - email: Updated recipient email address\n - type: Updated notification type. Valid types: report, update, alert, reminder, solution_proposal, other (all lowercase, case-sensitive)\n - status: Updated notification status. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled (all lowercase, case-sensitive)\n \n Example payload:\n {\n \"notification_id\": 1,\n \"status\": \"ready\",\n \"type\": \"alert\"\n }",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "integer",
+ "description": "Notification ID to update (required)"
+ },
+ "hr_case_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Updated HR case ID"
+ },
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated recipient email address"
+ },
+ "type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated notification type (report, update, alert, reminder, solution_proposal, other)"
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated notification status (draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled)"
+ }
+ },
+ "required": [
+ "notification_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "delete_notifications",
+ "title": null,
+ "description": "Delete notifications with optional filters, scoped to user's organization.\n \n Deletes notifications matching all provided filters (AND logic).\n \n Required filters (at least one):\n - notification_id: Exact match on notification ID (unique identifier)\n - hr_case_id: Exact match on HR case ID\n - email: Exact match on email address\n - type: Exact match on notification type. Valid types: report, update, alert, reminder, solution_proposal, other (all lowercase, case-sensitive)\n - status: Exact match on notification status. Valid statuses: draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled (all lowercase, case-sensitive)\n - sys_created_on: Exact match on created date/time (ISO 8601 format)\n - created_before: Filter notifications created before date (ISO 8601 format)\n - created_after: Filter notifications created after date (ISO 8601 format)\n \n Returns the number of notifications deleted.\n If no notifications match the filters, returns an error.\n \n Example:\n {\n \"notification_id\": 1\n }\n \n or\n \n {\n \"hr_case_id\": 1,\n \"status\": \"cancelled\"\n }",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by notification ID (exact match, unique identifier)"
+ },
+ "hr_case_id": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by HR case ID (exact match)"
+ },
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by email address (exact match)"
+ },
+ "type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification type (report, update, alert, reminder, solution_proposal, other)"
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification status (draft, ready, awaiting_approval, work_in_progress, closed_complete, closed_incomplete, awaiting_acceptance, suspended, cancelled)"
+ },
+ "sys_created_on": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by created date/time (ISO 8601 format, exact match)"
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter notifications created before date (ISO 8601 format)"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter notifications created after date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_hr_case_tasks",
+ "title": null,
+ "description": "Flexible search for HR case tasks with multiple filter options. Returns matching tasks with all related entities (assigned user, assignment group, HR service, and parent case) fully expanded. All filters use AND logic. Results are automatically scoped to the authenticated user's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_task_id": {
+ "type": "string",
+ "description": "Filter by exact task ID (optional)"
+ },
+ "number": {
+ "type": "string",
+ "description": "Filter by exact task number (optional)"
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by exact task status (optional)",
+ "enum": [
+ "draft",
+ "ready",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "cancelled"
+ ]
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Filter by assigned user name in format 'first_name last_name' (optional)"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Filter by assignment group name (optional)"
+ },
+ "task_type": {
+ "type": "string",
+ "description": "Filter by exact task type (optional)",
+ "enum": [
+ "checklist",
+ "survey",
+ "hr service",
+ "mark when complete",
+ "url"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "Filter by HR service name (optional)"
+ },
+ "external_url": {
+ "type": "string",
+ "description": "Filter by external URL - partial match, case-insensitive (optional)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Filter by short description - partial match, case-insensitive (optional)"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Filter by worknotes - partial match, case-insensitive (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status (optional)"
+ },
+ "parent_case": {
+ "type": "string",
+ "description": "Filter by exact parent case ID (optional)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_hr_case_task",
+ "title": null,
+ "description": "Create a new HR case task with complete validation. Validates all referenced entities (parent case, assigned user, assignment group, HR service) exist in the database and belong to the organization. Automatically generates a unique task number in format TASK-YYYYMMDD-XXXX. The task is automatically scoped to the authenticated user's organization. short_description must contain at least one non-whitespace character. Returns the created task with all relationships fully expanded.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "description": "Task status (required)",
+ "enum": [
+ "draft",
+ "ready",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "cancelled"
+ ]
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description of the task (required, must contain at least one non-whitespace character)"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Assigned user name in format 'first_name last_name' - must exist in database (optional)"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group name - must exist in database (optional)"
+ },
+ "task_type": {
+ "type": "string",
+ "description": "Task type (optional)",
+ "enum": [
+ "checklist",
+ "survey",
+ "hr service",
+ "mark when complete",
+ "url"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "HR service name - must exist in database (optional)"
+ },
+ "external_url": {
+ "type": "string",
+ "description": "External URL (optional)"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Worknotes (optional)"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether task is active and available. Defaults to true.",
+ "default": true
+ },
+ "parent_case": {
+ "type": "string",
+ "description": "Parent case ID - must exist in database (optional)"
+ }
+ },
+ "required": [
+ "status",
+ "short_description"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_hr_case_task",
+ "title": null,
+ "description": "Update an existing HR case task with smart change detection. Validates all field changes and prevents unnecessary updates by detecting if fields are already set to the provided values. Validates that referenced entities exist and belong to the organization. The task must belong to the authenticated user's organization. Updates only the fields provided and automatically sets the updated_at timestamp. If updating short_description, it must contain at least one non-whitespace character. Returns the updated task with all relationships fully expanded.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "hr_case_task_id": {
+ "type": "string",
+ "description": "ID of the HR case task to update (must exist in database). Example: 1"
+ },
+ "number": {
+ "type": "string",
+ "description": "New task number - must be unique (optional). Only provide if changing."
+ },
+ "status": {
+ "type": "string",
+ "description": "New task status (optional). Only provide if changing.",
+ "enum": [
+ "draft",
+ "ready",
+ "work_in_progress",
+ "closed_complete",
+ "closed_incomplete",
+ "cancelled"
+ ]
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "New assigned user name in format 'first_name last_name' - must exist in database (optional). Only provide if changing."
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "New assignment group name - must exist in database (optional). Only provide if changing."
+ },
+ "task_type": {
+ "type": "string",
+ "description": "New task type (optional). Only provide if changing.",
+ "enum": [
+ "checklist",
+ "survey",
+ "hr service",
+ "mark when complete",
+ "url"
+ ]
+ },
+ "hr_service": {
+ "type": "string",
+ "description": "New HR service name - must exist in database (optional). Only provide if changing."
+ },
+ "external_url": {
+ "type": "string",
+ "description": "New external URL (optional). Only provide if changing."
+ },
+ "short_description": {
+ "type": "string",
+ "description": "New short description (optional). Only provide if changing. Must contain at least one non-whitespace character if provided."
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "New worknotes (optional). Only provide if changing."
+ },
+ "active": {
+ "type": "boolean",
+ "description": "New active status (optional). Only provide if changing."
+ },
+ "parent_case": {
+ "type": "string",
+ "description": "New parent case ID - must exist in database (optional). Only provide if changing."
+ }
+ },
+ "required": [
+ "hr_case_task_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/itsm.json b/resources_servers/enterpriseops_gym/data/tools/itsm.json
new file mode 100644
index 0000000000..4733e18bbd
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/itsm.json
@@ -0,0 +1,5223 @@
+{
+ "gym_name": "gym-itsm-mcp",
+ "gym_url": "http://localhost:8006",
+ "snapshot_at": "2026-07-07T17:47:19.235473+00:00",
+ "tools": [
+ {
+ "name": "get_user_using_email",
+ "title": null,
+ "description": "Retrieve a user by their email address.\n \n Use this tool to find a specific user using their email address as the identifier.\n The email must be in valid format (e.g., user@domain.com).\n \n Authentication Requirements:\n - x-itsm-user-token: Optional valid user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Parameters:\n - email (required): User's email address\n \n Returns a single user object if found, or an error if the user doesn't exist or email format is invalid.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "User's email address",
+ "format": "email"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_user",
+ "title": null,
+ "description": "Retrieve a user by their user ID.\n \n Use this tool to find a specific user using their unique user_id identifier.\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Parameters:\n - user_id (required): User's unique identifier (format: USER_001, USER_002, etc.)\n \n Returns a single user object if found, or an error if the user doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "User's unique identifier (String, max 32 characters)"
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_user_using_name",
+ "title": null,
+ "description": "Retrieve a user by their first and last name combination.\n \n Use this tool to find a specific user using both their first name and last name.\n The search is case-insensitive.\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Parameters:\n - first_name (required): User's first name\n - last_name (required): User's last name\n \n Returns a single user object if found, or an error if no user matches the name combination.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "first_name": {
+ "type": "string",
+ "description": "User's first name"
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name"
+ }
+ },
+ "required": [
+ "first_name",
+ "last_name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_users",
+ "title": null,
+ "description": "List users with optional filters.\n \n Use this tool to retrieve a list of users. Without filters, returns all users.\n With filters, returns only users matching the specified criteria.\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Optional Filters:\n - email: Filter by exact email address\n - user_id: Filter by exact user ID\n - first_name: Filter by first name (case-insensitive, partial match)\n - last_name: Filter by last name (case-insensitive, partial match)\n - phone: Filter by phone number (format: +1-415-555-0101)\n - role: Filter by role (admin, manager, agent, reporter)\n - active: Filter by active status (true or false)\n - created_after: Filter users created after date (ISO 8601 format: 2024-01-15 or 2024-01-15T09:00:00)\n - created_before: Filter users created before date (ISO 8601 format)\n \n Returns a list of user objects matching the filters, or all users if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by email address (exact match)",
+ "default": ""
+ },
+ "user_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by user ID (exact match)",
+ "default": ""
+ },
+ "first_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by first name (partial match)",
+ "default": ""
+ },
+ "last_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by last name (partial match)",
+ "default": ""
+ },
+ "phone": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by phone number (partial match)",
+ "default": ""
+ },
+ "role": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by user role (admin, manager, agent, reporter)",
+ "default": ""
+ },
+ "active": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by active status (true/false)",
+ "default": ""
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter users created after this date (ISO 8601 format)",
+ "default": ""
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter users created before this date (ISO 8601 format)",
+ "default": ""
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_user",
+ "title": null,
+ "description": "Create a new user in the system.\n \n Use this tool to add a new user with the specified details. The system automatically generates\n user_id (incremental: USER_001, USER_002, etc.), user_name (from first.last), and other system fields.\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Required Parameters:\n - first_name: User's first name (1-60 characters)\n - last_name: User's last name (1-60 characters)\n - email: User's email address (must be unique and valid format)\n - phone: User's phone number (format: +1-415-555-0101, must be unique)\n - role: User's role (must be one of: admin, manager, agent, reporter)\n - active: Whether the user account is active (true or false)\n \n Optional Parameters:\n - user_name: User login name (generated from first.last if not provided)\n - location_id: Location identifier\n \n Note: The organization ID (org_id) is automatically set from the authenticated user's organization.\n \n Auto-Generated Fields:\n - user_id: Incremental ID (USER_001, USER_002, etc.)\n - user_name: Generated from first_name.last_name (lowercase)\n - static_token: Secure authentication token\n - created_on and updated_on timestamps\n - sys_id and other audit fields\n \n Returns the newly created user object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "first_name": {
+ "type": "string",
+ "description": "User's first name (non-empty string, 1-60 characters)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "last_name": {
+ "type": "string",
+ "description": "User's last name (non-empty string, 1-60 characters)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "email": {
+ "type": "string",
+ "description": "User's email address (valid email format required)",
+ "format": "email"
+ },
+ "phone": {
+ "type": "string",
+ "description": "User's phone number (format: +1-415-555-0101)",
+ "pattern": "^\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}$"
+ },
+ "role": {
+ "type": "string",
+ "description": "User's role in the system",
+ "enum": [
+ "admin",
+ "manager",
+ "agent",
+ "reporter"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the user account is active"
+ },
+ "user_name": {
+ "type": "string",
+ "description": "User login name (generated from first.last if not provided)"
+ },
+ "location_id": {
+ "type": "string",
+ "description": "Location identifier",
+ "default": ""
+ }
+ },
+ "required": [
+ "first_name",
+ "last_name",
+ "email",
+ "phone",
+ "role",
+ "active"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_user_details",
+ "title": null,
+ "description": "Update specific fields of an existing user.\n \n Use this tool to update one or more fields of a user identified by user_id.\n At least one field (besides user_id) must be provided. The tool validates that\n the new values are different from current values (idempotency check).\n \n Authentication Requirements:\n - x-itsm-user-token: Optional user authentication token. Validates the requester's identity.\n - API returns 401 Unauthorized if provided token is invalid.\n \n Required Parameter:\n - user_id: Unique identifier of the user to update\n \n Optional Parameters (at least one required):\n - email: Updated email address (must be unique and valid format)\n - first_name: Updated first name (1-60 characters)\n - last_name: Updated last name (1-60 characters)\n - active: Updated active status (true or false)\n - phone: Updated phone number (format: +1-415-555-0101, must be unique)\n - role: Updated role (must be one of: admin, manager, agent, reporter)\n - user_name: Updated user login name (must be unique)\n - company_id: Updated company identifier\n - location_id: Updated location identifier\n \n Note: Updating a field to its current value will result in an error (no changes detected).\n System fields like sys_id, created_on, etc. cannot be directly modified.\n \n Returns the updated user object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "User's unique identifier to identify which user to update"
+ },
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated email address (valid email format required)",
+ "format": "email"
+ },
+ "first_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated first name (non-empty string, 1-60 characters)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "last_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated last name (non-empty string, 1-60 characters)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Updated active status"
+ },
+ "phone": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated phone number (format: +1-415-555-0101)",
+ "pattern": "^\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}$"
+ },
+ "role": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated user role",
+ "enum": [
+ "admin",
+ "manager",
+ "agent",
+ "reporter"
+ ]
+ },
+ "user_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated user login name (must be unique)",
+ "default": ""
+ },
+ "company_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated company identifier",
+ "default": ""
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated location identifier",
+ "default": ""
+ }
+ },
+ "required": [
+ "user_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_user_groups",
+ "title": null,
+ "description": "List user groups with optional filters. Returns all user groups or filtered results based on provided criteria. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "Filter by group ID (exact match)",
+ "default": ""
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by group name (partial match)",
+ "default": ""
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Filter by active status"
+ },
+ "type": {
+ "type": "string",
+ "description": "Filter by group type",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ]
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter groups created after this date (ISO 8601 format)",
+ "default": ""
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter groups created before this date (ISO 8601 format)",
+ "default": ""
+ }
+ },
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_group_by_name",
+ "title": null,
+ "description": "Find a user group by its exact name. Returns the group details if found. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The exact name of the user group to find"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_user_group",
+ "title": null,
+ "description": "Add a new user group to the system. Group name must be unique. Returns the newly created group object. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Group's name",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "type": {
+ "type": "string",
+ "description": "Group's type",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the group is active",
+ "default": true
+ },
+ "email": {
+ "type": "string",
+ "description": "Group's email address",
+ "format": "email",
+ "default": ""
+ },
+ "description": {
+ "type": "string",
+ "description": "Group's description",
+ "default": ""
+ },
+ "manager_id": {
+ "type": "string",
+ "description": "Group manager's user ID",
+ "default": ""
+ }
+ },
+ "required": [
+ "name",
+ "type"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_user_group",
+ "title": null,
+ "description": "Update user group details. At least one field must be provided. Group name must be unique if provided. Returns error if all fields match current values (idempotency validation). Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "Group's unique identifier",
+ "default": ""
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated group name",
+ "minLength": 1,
+ "maxLength": 80,
+ "default": ""
+ },
+ "type": {
+ "type": "string",
+ "description": "Updated group type",
+ "enum": [
+ "IT Support",
+ "Service Desk",
+ "Field Support Technicians",
+ "Infrastructure Problem Team"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Updated active status"
+ }
+ },
+ "required": [
+ "group_id"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_group_member",
+ "title": null,
+ "description": "Add a new group member to a user group. Validates that group and user exist, and that the user is not already a member. Returns the newly created membership object. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "Group's unique identifier",
+ "default": ""
+ },
+ "user_id": {
+ "type": "string",
+ "description": "User's unique identifier",
+ "default": ""
+ }
+ },
+ "required": [
+ "group_id",
+ "user_id"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_group_membership",
+ "title": null,
+ "description": "Remove group membership from a user group. Validates that group, user, and optional member_id exist. Member_id must match the group_id and user_id if provided. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "group_id": {
+ "type": "string",
+ "description": "Group's unique identifier",
+ "default": ""
+ },
+ "user_id": {
+ "type": "string",
+ "description": "User's unique identifier",
+ "default": ""
+ },
+ "member_id": {
+ "type": "string",
+ "description": "Member's unique identifier (optional for additional validation)",
+ "default": ""
+ }
+ },
+ "required": [
+ "group_id",
+ "user_id"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_group_members",
+ "title": null,
+ "description": "List group members with optional filters. Returns all group members or filtered results based on provided criteria. Requires x-itsm-user-token for authentication requirements. Returns 401 Unauthorized if token is invalid or missing. Response includes sys_* audit fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "member_id": {
+ "type": "string",
+ "description": "Filter by member ID (exact match)",
+ "default": ""
+ },
+ "group_id": {
+ "type": "string",
+ "description": "Filter by group ID (exact match)",
+ "default": ""
+ },
+ "user_id": {
+ "type": "string",
+ "description": "Filter by user ID (exact match)",
+ "default": ""
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter members created after this date (ISO 8601 format)",
+ "default": ""
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter members created before this date (ISO 8601 format)",
+ "default": ""
+ }
+ },
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_location_by_given_name",
+ "title": null,
+ "description": "Find a location by its name.\n \n Use this tool to find a specific location using its name as the identifier.\n The search is case-sensitive and requires an exact name match.\n \n Parameters:\n - name (required): Location name to search for\n \n Returns a single location object if found, or an error if the location doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the location to find"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_locations",
+ "title": null,
+ "description": "List locations with optional filters.\n \n Use this tool to retrieve a list of locations. Without filters, returns all locations.\n With filters, returns only locations matching the specified criteria.\n \n Optional Filters:\n - name: Filter by location name (partial match)\n - city: Filter by city (partial match)\n - country: Filter by country (partial match)\n - active: Filter by active status (true or false)\n - created_after: Filter locations created after date (ISO 8601 format: 2024-01-01 or 2024-01-01T08:00:00)\n - created_before: Filter locations created before date (ISO 8601 format)\n \n Returns a list of location objects matching the filters, or all locations if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by location name (partial match)",
+ "default": ""
+ },
+ "city": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by city (partial match)",
+ "default": ""
+ },
+ "country": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by country (partial match)",
+ "default": ""
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Filter by active status (true/false)",
+ "default": true
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter locations created after this date (ISO 8601 format)",
+ "default": ""
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter locations created before this date (ISO 8601 format)",
+ "default": ""
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_location",
+ "title": null,
+ "description": "Create a new location in the system.\n \n Use this tool to add a new location with the specified details. The system automatically generates\n location_id (incremental: LOC_001, LOC_002, etc.) and timestamps.\n \n Required Parameters:\n - name: Location name (must be unique)\n - city: City name (cannot be empty)\n - country: Country (cannot be empty)\n \n Optional Parameters:\n - active: Whether the location is active (default: true)\n - plot_no: Plot/building number\n - street: Street address\n - state: State/province/region\n \n Auto-Generated Fields:\n - location_id: Incremental ID (LOC_001, LOC_002, etc.)\n - created_on and updated_on timestamps\n \n Returns the newly created location object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Location name (must be unique)",
+ "minLength": 1
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Whether the location is active",
+ "default": true
+ },
+ "plot_no": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Plot/building number",
+ "default": ""
+ },
+ "street": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Street address",
+ "default": ""
+ },
+ "city": {
+ "type": "string",
+ "description": "City name (cannot be empty)",
+ "minLength": 1
+ },
+ "state": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "State/province/region",
+ "default": ""
+ },
+ "country": {
+ "type": "string",
+ "description": "Country (cannot be empty)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name",
+ "city",
+ "country"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_location_by_id",
+ "title": null,
+ "description": "Get a location by its ID.\n \n Use this tool to find a specific location using its unique location_id identifier.\n \n Parameters:\n - location_id (required): Location's unique identifier (format: LOC_001, LOC_002, etc.)\n \n Returns a single location object if found, or an error if the location doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "string",
+ "description": "Location's unique identifier"
+ }
+ },
+ "required": [
+ "location_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_location",
+ "title": null,
+ "description": "Update specific fields of an existing location.\n \n Use this tool to update one or more fields of a location identified by location_id.\n At least one field (besides location_id) must be provided. The tool validates that\n the new values are different from current values (idempotency check).\n \n Required Parameter:\n - location_id: Unique identifier of the location to update\n \n Optional Parameters (at least one required):\n - name: Updated location name (must be unique)\n - active: Updated active status\n - plot_no: Updated plot/building number\n - street: Updated street address\n - city: Updated city name (cannot be empty if provided)\n - state: Updated state/province/region\n - country: Updated country (cannot be empty if provided)\n \n Note: If updating city or country, they cannot be empty strings.\n \n Note: Updating a field to its current value will result in an error (no changes detected).\n \n Returns the updated location object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "location_id": {
+ "type": "string",
+ "description": "Location's unique identifier to identify which location to update"
+ },
+ "name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated location name (must be unique)",
+ "default": ""
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Updated active status",
+ "default": true
+ },
+ "plot_no": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated plot/building number",
+ "default": ""
+ },
+ "street": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated street address",
+ "default": ""
+ },
+ "city": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated city name (cannot be empty if provided)",
+ "minLength": 1
+ },
+ "state": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated state/province/region",
+ "default": ""
+ },
+ "country": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated country (cannot be empty if provided)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "location_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_new_incident_template",
+ "title": null,
+ "description": "Create a new incident template in the system.\n \n Use this tool to add a new incident template with the specified details. The system automatically\n generates incident_template_id (incremental: TMPL_001, TMPL_002, etc.) and timestamps.\n \n Required Parameters:\n - name: Template name (1-120 characters, must be unique)\n - change_request_values: JSON object containing template fields\n \n Required fields inside change_request_values:\n - caller_id: User ID who is the default caller\n - short_description: Brief description (1-120 characters)\n \n Optional fields inside change_request_values:\n - channel: Incident channel (values: SELF_SERVICE, PHONE, EMAIL, CHAT, WALK_IN, VIRTUAL_AGENT)\n - category: Incident category (values: INQUIRY_HELP, SOFTWARE, HARDWARE, DATABASE, PASSWORD_RESET)\n - impact: Impact level (values: HIGH, MEDIUM, LOW) - defaults to LOW\n - urgency: Urgency level (values: HIGH, MEDIUM, LOW) - defaults to LOW\n - priority: Priority level (values: CRITICAL, HIGH, MODERATE, LOW, PLANNING) - defaults to PLANNING\n - configuration_item: Configuration item ID\n - service: Service ID\n - service_offering: Service offering ID\n \n Optional Parameters:\n - active: Whether the template is active (defaults to true)\n \n Auto-Generated Fields:\n - incident_template_id: Incremental ID (TMPL_001, TMPL_002, etc.)\n - created_at and updated_at timestamps\n \n Returns the newly created incident template object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Template name (unique, 1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "change_request_values": {
+ "type": "object",
+ "description": "JSON object containing template fields. Required: caller_id, short_description. Optional: channel, category, impact, urgency, priority, configuration_item, service, service_offering",
+ "properties": {
+ "caller_id": {
+ "type": "string",
+ "description": "Default caller user ID (required)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Brief description (required, 1-120 characters)"
+ },
+ "channel": {
+ "type": "string",
+ "description": "Incident channel",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "category": {
+ "type": "string",
+ "description": "Incident category",
+ "enum": [
+ "inquiry-help",
+ "software",
+ "hardware",
+ "database",
+ "password-reset"
+ ]
+ },
+ "impact": {
+ "type": "string",
+ "description": "Impact level (defaults to 'low')",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "urgency": {
+ "type": "string",
+ "description": "Urgency level (defaults to 'low')",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "priority": {
+ "type": "string",
+ "description": "Priority level (defaults to 'planning')",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Configuration item ID"
+ },
+ "service": {
+ "type": "string",
+ "description": "Service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Service offering ID"
+ }
+ },
+ "required": [
+ "caller_id",
+ "short_description"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the template is active (defaults to true)"
+ }
+ },
+ "required": [
+ "name",
+ "change_request_values"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_incident_template",
+ "title": null,
+ "description": "Update specific fields of an existing incident template.\n \n Use this tool to update one or more fields of an incident template identified by incident_template_id.\n At least one field (besides incident_template_id) must be provided. The tool validates that\n the new values are different from current values (idempotency check).\n \n IMPORTANT - Field Update Behavior:\n - Empty strings (\"\") are IGNORED - the field will not be updated\n - Explicit null values for nullable fields (channel, category, configuration_item, service, service_offering) will SET the field to null\n - Only fields with actual values will be validated and updated\n - At least one field must be provided with a non-empty value\n \n Required Parameter:\n - incident_template_id: Unique identifier of the template to update\n \n Optional Parameters (at least one required):\n - name: Updated template name (1-120 characters, must be unique)\n * Empty string (\"\") = ignore, don't update\n * Valid string = update to this value\n - change_request_values: JSON object containing any of these fields:\n * caller_id: Updated caller user ID (empty string = ignore)\n * short_description: Updated brief description (empty string = ignore)\n * channel: Updated incident channel (self-service, phone, email, chat, walk-in, virtual-agent)\n - Empty string (\"\") = ignore, don't update\n - null = set to null (clear the field)\n - Valid value = update to this value\n * category: Updated incident category (inquiry-help, software, hardware, database, password-reset)\n - Empty string (\"\") = ignore, don't update\n - null = set to null (clear the field)\n - Valid value = update to this value\n * impact: Updated impact level (high, medium, low) (empty string = ignore)\n * urgency: Updated urgency level (high, medium, low) (empty string = ignore)\n * priority: Updated priority level (critical, high, moderate, low, planning) (empty string = ignore)\n * configuration_item: Updated configuration item ID\n - Empty string (\"\") = ignore, don't update\n - null = set to null (clear the field)\n - Valid ID = update to this value\n * service: Updated service ID\n - Empty string (\"\") = ignore, don't update\n - null = set to null (clear the field)\n - Valid ID = update to this value\n * service_offering: Updated service offering ID\n - Empty string (\"\") = ignore, don't update\n - null = set to null (clear the field)\n - Valid ID = update to this value\n - active: Updated active status\n * null = ignore, don't update\n * true/false = update to this value\n \n Note: Updating a field to its current value will result in an error (no changes detected).\n \n Returns the updated incident template object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_template_id": {
+ "type": "string",
+ "description": "Unique identifier of the incident template to update"
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated template name (1-120 characters, must be unique). Empty string (\"\") = ignore, don't update",
+ "default": "",
+ "minLength": 0,
+ "maxLength": 120
+ },
+ "change_request_values": {
+ "type": "object",
+ "description": "JSON object containing template fields to update. Empty strings (\"\") = ignore field. null for nullable fields = set to null. Can include: caller_id, short_description, channel, category, impact, urgency, priority, configuration_item, service, service_offering",
+ "default": {
+ "caller_id": "",
+ "short_description": "",
+ "channel": "",
+ "category": "",
+ "impact": "",
+ "urgency": "",
+ "priority": "",
+ "configuration_item": "",
+ "service": "",
+ "service_offering": ""
+ },
+ "properties": {
+ "caller_id": {
+ "type": "string",
+ "description": "Updated caller user ID. Empty string (\"\") = ignore, don't update"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Updated brief description. Empty string (\"\") = ignore, don't update"
+ },
+ "channel": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated incident channel. Empty string (\"\") = ignore, null = set to null, valid value = update",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "category": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated incident category. Empty string (\"\") = ignore, null = set to null, valid value = update",
+ "enum": [
+ "inquiry-help",
+ "software",
+ "hardware",
+ "database",
+ "password-reset"
+ ]
+ },
+ "impact": {
+ "type": "string",
+ "description": "Updated impact level. Empty string (\"\") = ignore, don't update",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "urgency": {
+ "type": "string",
+ "description": "Updated urgency level. Empty string (\"\") = ignore, don't update",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "priority": {
+ "type": "string",
+ "description": "Updated priority level. Empty string (\"\") = ignore, don't update",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "configuration_item": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated configuration item ID. Empty string (\"\") = ignore, null = set to null, valid ID = update"
+ },
+ "service": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated service ID. Empty string (\"\") = ignore, null = set to null, valid ID = update"
+ },
+ "service_offering": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated service offering ID. Empty string (\"\") = ignore, null = set to null, valid ID = update"
+ }
+ }
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Updated active status. null = ignore, don't update. true/false = update to this value"
+ }
+ },
+ "required": [
+ "incident_template_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_incident_template_by_name",
+ "title": null,
+ "description": "Retrieve an incident template by its exact name.\n \n Use this tool to find a specific incident template using its name as the identifier.\n The search is case-sensitive and requires an exact match.\n \n Parameters:\n - name (required): Incident template name\n \n Returns a single incident template object if found, or an error if the template doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Incident template name (exact match, case-sensitive)"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_incident_templates",
+ "title": null,
+ "description": "List incident templates with optional filters.\n \n Use this tool to retrieve a list of incident templates. Without filters, returns all templates.\n With filters, returns only templates matching the specified criteria.\n \n Optional Filters:\n - incident_template_id: Filter by exact template ID\n - name: Filter by template name (exact match)\n - active: Filter by active status (boolean: true or false)\n - created_after: Filter templates created after date (ISO 8601 format: 2024-01-15 or 2024-01-15T09:00:00)\n - created_before: Filter templates created before date (ISO 8601 format)\n \n Returns a list of incident template objects matching the filters, or all templates if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_template_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by incident template ID (exact match)"
+ },
+ "name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by template name (exact match)"
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Filter by active status (true or false)"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter templates created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter templates created before this date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "register_configuration_item",
+ "title": null,
+ "description": "Register a new configuration item in the system.\n \n Use this tool to add a new configuration item (CI) with the specified details.\n The system automatically generates configuration_item_id (CI_001, CI_002, etc.) and timestamps.\n \n Required Parameters:\n - name: CI name (1-120 characters, required)\n - owner_id: User ID who owns the CI\n - location_id: Location ID where CI is located\n - serial_number: Serial number (must be unique, 1-60 characters)\n - status: CI status (values: IN_USE, IN_STOCK, MAINTENANCE, RETIRED, DISPOSED)\n - cost: Cost of the CI (must be >= 0)\n \n Auto-Generated Fields:\n - configuration_item_id: Incremental ID (CI_001, CI_002, etc.)\n - created_on and updated_on timestamps\n \n Unique Constraints:\n - name must be unique across all CIs\n - serial_number must be unique across all CIs\n - Combination of (owner_id, serial_number, location_id) must be unique\n \n Returns the newly created configuration item object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "CI name (required, 1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "owner_id": {
+ "type": "string",
+ "description": "User ID who owns the CI"
+ },
+ "location_id": {
+ "type": "string",
+ "description": "Location ID where CI is located"
+ },
+ "serial_number": {
+ "type": "string",
+ "description": "Serial number (unique, 1-60 characters)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "status": {
+ "type": "string",
+ "description": "CI status (in_use, in_stock, maintenance, retired, disposed)",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "maintenance",
+ "retired",
+ "disposed"
+ ]
+ },
+ "cost": {
+ "type": "number",
+ "description": "Cost of the CI (must be >= 0)",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "name",
+ "owner_id",
+ "location_id",
+ "serial_number",
+ "status",
+ "cost"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_configuration_item",
+ "title": null,
+ "description": "Update specific fields of an existing configuration item.\n \n Use this tool to update one or more fields of a CI identified by configuration_item_id.\n At least one field (besides configuration_item_id) must be provided. The tool validates that\n the new values are different from current values (idempotency check).\n \n Required Parameter:\n - configuration_item_id: Unique identifier of the CI to update\n \n Optional Parameters (at least one required):\n - owner_id: Updated owner user ID\n - location_id: Updated location ID\n - serial_number: Updated serial number (must remain unique)\n - status: Updated CI status (IN_USE, IN_STOCK, MAINTENANCE, RETIRED, DISPOSED)\n - cost: Updated cost (must be >= 0)\n - name: Updated CI name\n \n Unique Constraints:\n - If serial_number is updated, it must be unique\n - If owner_id, serial_number, or location_id are updated, the combination must be unique\n \n Note: Updating a field to its current value will result in an error (no changes detected).\n \n Returns the updated configuration item object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "configuration_item_id": {
+ "type": "string",
+ "description": "Unique identifier of the CI to update"
+ },
+ "owner_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated owner user ID"
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated location ID"
+ },
+ "serial_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated serial number (must remain unique)",
+ "minLength": 1,
+ "maxLength": 60
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated CI status (in_use, in_stock, maintenance, retired, disposed)",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "maintenance",
+ "retired",
+ "disposed"
+ ]
+ },
+ "cost": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "description": "Updated cost (must be >= 0)",
+ "minimum": 0
+ },
+ "name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Updated CI name",
+ "maxLength": 120
+ }
+ },
+ "required": [
+ "configuration_item_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_configuration_item_by_serial_number",
+ "title": null,
+ "description": "Retrieve a configuration item by its serial number.\n \n Use this tool to find a specific CI using its serial number as the identifier.\n The serial number is unique across all configuration items.\n \n Parameters:\n - serial_number (required): Configuration item serial number\n \n Returns a single configuration item object if found, or an error if the CI doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "serial_number": {
+ "type": "string",
+ "description": "Configuration item serial number (exact match)"
+ }
+ },
+ "required": [
+ "serial_number"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_configuration_items",
+ "title": null,
+ "description": "List configuration items with optional filters.\n \n Use this tool to retrieve a list of configuration items. Without filters, returns all CIs.\n With filters, returns only CIs matching the specified criteria.\n \n Optional Filters:\n - configuration_item_id: Filter by CI ID (exact match)\n - owner_id: Filter by owner user ID (exact match)\n - location_id: Filter by location ID (exact match)\n - serial_number: Filter by serial number (exact match)\n - status: Filter by status (IN_USE, IN_STOCK, MAINTENANCE, RETIRED, DISPOSED)\n - cost: Filter by cost (exact match)\n - created_after: Filter CIs created after date (ISO 8601 format: 2024-01-15 or 2024-01-15T09:00:00)\n - created_before: Filter CIs created before date (ISO 8601 format)\n \n Returns a list of configuration item objects matching the filters, or all CIs if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "configuration_item_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by configuration item ID (exact match)"
+ },
+ "owner_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by owner user ID (exact match)"
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by location ID (exact match)"
+ },
+ "serial_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by serial number (exact match)"
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by status",
+ "enum": [
+ "in_use",
+ "in_stock",
+ "maintenance",
+ "retired",
+ "disposed"
+ ]
+ },
+ "cost": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "description": "Filter by cost (exact match)"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter CIs created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter CIs created before this date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_services",
+ "title": null,
+ "description": "List services with optional filters. Returns all services or filtered results.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_id": {
+ "type": "string",
+ "description": "Filter by service ID (exact match)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by service name (partial match)"
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Filter by owner"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Filter by usage",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Filter by classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Filter by criticality",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter services created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter services created before this date (ISO 8601 format)"
+ }
+ },
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_service_by_name",
+ "title": null,
+ "description": "Find a service by its exact name. Returns the service details if found.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The exact name of the service to find"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_service",
+ "title": null,
+ "description": "Add a new service to the system. Service name must be unique. Returns the newly created service object.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Service name",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Owner of the service"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Purpose/usage of the service",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Service status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Service classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Business criticality level",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "Description of the service"
+ }
+ },
+ "required": [
+ "name",
+ "owned_by"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_service",
+ "title": null,
+ "description": "Update service details. At least one field must be provided. Service name must be unique if provided. Returns error if all fields match current values (idempotency validation).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_id": {
+ "type": "string",
+ "description": "Service's unique identifier"
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated service name",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Updated owner"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Updated usage/purpose",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Updated status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Updated classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Updated business criticality",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "description": "Description of the service"
+ }
+ },
+ "required": [
+ "service_id"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_change",
+ "title": null,
+ "description": "Create a new change request.\n\nAutomatically generates:\n- change_id (CHG_001, CHG_002, ...)\n- number (CHG0000001, CHG0000002, ...)\n\nRequired fields:\n- short_description: Brief description (<=120 chars)\n- status: Change status (new, assess, authorize, scheduled, implement, review, closed, canceled)\n- impact: Impact level (high, medium, low)\n- risk: Risk level (high, medium, low)\n- priority: Priority level (critical, high, moderate, low)\n\nOptional fields:\n- service: Service ID\n- service_offering: Service offering ID\n- configuration_item: Configuration item ID\n- category: Change category (network, software, hardware, documentation, system_software, application_software, service, telecom, other)\n- description: Detailed description (<=120 chars)\n- implementation_plan: Implementation plan (<=120 chars)\n- testing_plan: Testing plan (<=120 chars)\n- cab_required: Boolean indicating if CAB approval is needed\n- assigned_to: Assigned user ID\n- assignment_group: Assigned group ID\n- close_code: Close code (successful, successful_with_issues, unsuccessful)\n- close_notes: Close notes (<=120 chars)\n\nExample payload:\n{\n \"short_description\": \"Upgrade database cluster\",\n \"status\": \"assess\",\n \"impact\": \"high\",\n \"risk\": \"high\",\n \"priority\": \"critical\",\n \"category\": \"service\",\n \"implementation_plan\": \"Rollover to replica, upgrade primary, fail back\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "short_description": {
+ "type": "string",
+ "description": "Short description (<=120 chars)"
+ },
+ "status": {
+ "type": "string",
+ "description": "Change status (new, assess, authorize, scheduled, implement, review, closed, canceled)"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Impact level (high, medium, low)"
+ },
+ "risk": {
+ "type": "string",
+ "description": "Risk level (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Priority level (critical, high, moderate, low)"
+ },
+ "service": {
+ "type": "string",
+ "description": "Service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Configuration item ID"
+ },
+ "category": {
+ "type": "string",
+ "description": "Change category (network, software, hardware, documentation, system_software, application_software, service, telecom, other)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Detailed description (<=120 chars)"
+ },
+ "implementation_plan": {
+ "type": "string",
+ "description": "Implementation plan (<=120 chars)"
+ },
+ "testing_plan": {
+ "type": "string",
+ "description": "Testing plan (<=120 chars)"
+ },
+ "cab_required": {
+ "type": "boolean",
+ "description": "Whether CAB approval is required"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Assigned user ID"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assigned group ID"
+ },
+ "close_code": {
+ "type": "string",
+ "description": "Close code (successful, successful_with_issues, unsuccessful)"
+ },
+ "close_notes": {
+ "type": "string",
+ "description": "Close notes (<=120 chars)"
+ }
+ },
+ "required": [
+ "short_description",
+ "status",
+ "impact",
+ "risk",
+ "priority"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_change",
+ "title": null,
+ "description": "Update an existing change request by change_id.\n\nAll fields are optional; only provided fields are updated.\nIf no changes are detected, the API returns an error.\n\nExample payload:\n{\n \"change_id\": \"CHG_001\",\n \"status\": \"implement\",\n \"assigned_to\": \"USER_010\",\n \"implementation_plan\": \"Deploy patch to production nodes sequentially\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "change_id": {
+ "type": "string",
+ "description": "Change ID (CHG_001, CHG_002, ...). Required when calling this tool."
+ },
+ "number": {
+ "type": "string",
+ "description": "Change number (CHG0000001, CHG0000002, ...)"
+ },
+ "requested_by": {
+ "type": "string",
+ "description": "User ID who requested the change"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description (<=120 chars)"
+ },
+ "service": {
+ "type": "string",
+ "description": "Service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Configuration item ID"
+ },
+ "category": {
+ "type": "string",
+ "description": "Change category (network, software, hardware, documentation, system_software, application_software, service, telecom, other)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Detailed description (<=120 chars)"
+ },
+ "implementation_plan": {
+ "type": "string",
+ "description": "Implementation plan (<=120 chars)"
+ },
+ "testing_plan": {
+ "type": "string",
+ "description": "Testing plan (<=120 chars)"
+ },
+ "cab_required": {
+ "type": "boolean",
+ "description": "Whether CAB approval is required"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Assigned user ID"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Assigned group ID"
+ },
+ "close_code": {
+ "type": "string",
+ "description": "Close code (successful, successful_with_issues, unsuccessful)"
+ },
+ "close_notes": {
+ "type": "string",
+ "description": "Close notes (<=120 chars)"
+ },
+ "status": {
+ "type": "string",
+ "description": "Change status (new, assess, authorize, scheduled, implement, review, closed, canceled)"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Impact level (high, medium, low)"
+ },
+ "risk": {
+ "type": "string",
+ "description": "Risk level (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Priority level (critical, high, moderate, low)"
+ }
+ },
+ "required": [
+ "change_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_change_by_number",
+ "title": null,
+ "description": "Retrieve a change by its unique number (CHG0000001, CHG0000002, ...).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "type": "string",
+ "description": "Change number (CHG0000001, CHG0000002, ...)"
+ }
+ },
+ "required": [
+ "number"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_changes",
+ "title": null,
+ "description": "List changes applying optional filters. Returns all changes if no filters provided.\n\nSupported filters (all optional):\n- change_id, number, service, service_offering, configuration_item\n- requested_by, assigned_to, assignment_group\n- status, category, impact, risk, priority, close_code\n- short_description, description, implementation_plan, testing_plan, close_notes (partial match)\n- created_after, created_before (ISO timestamp strings)\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "change_id": {
+ "type": "string",
+ "description": "Filter by change_id"
+ },
+ "number": {
+ "type": "string",
+ "description": "Filter by change number"
+ },
+ "service": {
+ "type": "string",
+ "description": "Filter by service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Filter by service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Filter by configuration item ID"
+ },
+ "requested_by": {
+ "type": "string",
+ "description": "Filter by requester"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Filter by assigned user"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Filter by assignment group"
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by status (new, assess, authorize, scheduled, implement, review, closed, canceled)"
+ },
+ "category": {
+ "type": "string",
+ "description": "Filter by category (network, software, hardware, documentation, system_software, application_software, service, telecom, other)"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Filter by impact (high, medium, low)"
+ },
+ "risk": {
+ "type": "string",
+ "description": "Filter by risk (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Filter by priority (critical, high, moderate, low)"
+ },
+ "close_code": {
+ "type": "string",
+ "description": "Filter by close code (successful, successful_with_issues, unsuccessful)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Filter by short description (partial match)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Filter by description (partial match)"
+ },
+ "implementation_plan": {
+ "type": "string",
+ "description": "Filter by implementation plan (partial match)"
+ },
+ "testing_plan": {
+ "type": "string",
+ "description": "Filter by testing plan (partial match)"
+ },
+ "close_notes": {
+ "type": "string",
+ "description": "Filter by close notes (partial match)"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "ISO timestamp: return changes created after this value"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "ISO timestamp: return changes created before this value"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_changes_assigned_to",
+ "title": null,
+ "description": "Retrieve changes assigned to a specific user and/or assignment group.\n\nAt least one of assignment_group or assigned_to must be provided.\n\nExamples:\n{\n \"assignment_group\": \"GROUP_002\"\n}\n\n{\n \"assigned_to\": \"USER_005\"\n}\n\n{\n \"assignment_group\": \"GROUP_002\",\n \"assigned_to\": \"USER_005\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group": {
+ "type": "string",
+ "description": "Assignment group ID"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Assigned user ID"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_problem",
+ "title": null,
+ "description": "Create a new problem record.\n\nAuto-generates:\n- problem_id: PRB_001, PRB_002, etc.\n- number: PRB0000001, PRB0000002, etc.\n\nRequired fields:\n- problem_statement: Detailed problem statement\n- status: Problem status (NEW, ASSESS, ROOT_CAUSE, FIX_IN_PROGRESS, RESOLVED, CLOSED)\n- impact: Impact level (HIGH, MEDIUM, LOW)\n- urgency: Urgency level (HIGH, MEDIUM, LOW)\n- priority: Priority level (CRITICAL, HIGH, MODERATE, LOW, PLANNING)\n\nOptional fields:\n- short_description: Short description (max 255 chars)\n- service: Service ID\n- service_offering: Service offering ID\n- configuration_item: Configuration item ID\n- assigned_to: User ID assigned to\n- assignment_group: Group ID assigned to\n- original_task: Original incident ID\n- category: Problem category (NETWORK, SOFTWARE, HARDWARE, DATABASE)\n- worknotes: Work notes\n- workaround: Workaround description\n- fix_notes: Fix notes\n\nExample:\n{\n \"problem_statement\": \"Multiple users experiencing periodic email service disruptions\",\n \"status\": \"NEW\",\n \"impact\": \"HIGH\",\n \"urgency\": \"MEDIUM\",\n \"priority\": \"HIGH\",\n \"category\": \"NETWORK\",\n \"short_description\": \"Email service outages\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "problem_statement": {
+ "type": "string",
+ "description": "Detailed problem statement"
+ },
+ "status": {
+ "type": "string",
+ "description": "Problem status (new, assess, root_cause, fix_in_progress, resolved, closed)"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Impact level (high, medium, low)"
+ },
+ "urgency": {
+ "type": "string",
+ "description": "Urgency level (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Priority level (critical, high, moderate, low, planning)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description (max 255 chars)"
+ },
+ "service": {
+ "type": "string",
+ "description": "Service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Configuration item ID"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User ID assigned to"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Group ID assigned to"
+ },
+ "original_task": {
+ "type": "string",
+ "description": "Original incident ID"
+ },
+ "category": {
+ "type": "string",
+ "description": "Problem category (network, software, hardware, database)"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Work notes"
+ },
+ "workaround": {
+ "type": "string",
+ "description": "Workaround description"
+ },
+ "fix_notes": {
+ "type": "string",
+ "description": "Fix notes"
+ }
+ },
+ "required": [
+ "problem_statement",
+ "status",
+ "impact",
+ "urgency",
+ "priority"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_problem",
+ "title": null,
+ "description": "Update an existing problem by problem_id or number.\n\nCan update by:\n- problem_id: PRB_001, PRB_002, etc.\n- number: PRB0000001, PRB0000002, etc.\n\nAll fields are optional. Only provided fields will be updated.\nReturns error if no changes detected (idempotency).\n\nExample:\n{\n \"problem_id\": \"PRB_001\",\n \"status\": \"RESOLVED\",\n \"fix_notes\": \"Load balancer configuration corrected\"\n}\n\nOr update by number:\n{\n \"number\": \"PRB0000001\",\n \"assigned_to\": \"USER_007\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "problem_id": {
+ "type": "string",
+ "description": "Problem ID (e.g., PRB_001). Use either this or 'number', not both."
+ },
+ "number": {
+ "type": "string",
+ "description": "Problem number (e.g., PRB0000001). Use either this or 'problem_id', not both."
+ },
+ "opened_by": {
+ "type": "string",
+ "description": "User ID who opened the problem"
+ },
+ "problem_statement": {
+ "type": "string",
+ "description": "Detailed problem statement"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description"
+ },
+ "service": {
+ "type": "string",
+ "description": "Service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Configuration item ID"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "User ID assigned to"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Group ID assigned to"
+ },
+ "original_task": {
+ "type": "string",
+ "description": "Original incident ID"
+ },
+ "status": {
+ "type": "string",
+ "description": "Problem status (new, assess, root_cause, fix_in_progress, resolved, closed)"
+ },
+ "category": {
+ "type": "string",
+ "description": "Problem category (network, software, hardware, database)"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Work notes"
+ },
+ "workaround": {
+ "type": "string",
+ "description": "Workaround description"
+ },
+ "fix_notes": {
+ "type": "string",
+ "description": "Fix notes"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Impact level (high, medium, low)"
+ },
+ "urgency": {
+ "type": "string",
+ "description": "Urgency level (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Priority level (critical, high, moderate, low, planning)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_problem_by_number",
+ "title": null,
+ "description": "Find a problem by its unique problem number.\n\nThe number field is unique and follows the format PRB0000001, PRB0000002, etc.\n\nExample:\n{\n \"number\": \"PRB0000001\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "type": "string",
+ "description": "Problem number (e.g., PRB0000001)"
+ }
+ },
+ "required": [
+ "number"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_problems",
+ "title": null,
+ "description": "List problems with optional filters.\n\nAll filters are optional. Returns all problems if no filters provided.\n\nSupported filters:\n- problem_id: Exact match on problem ID\n- number: Exact match on number\n- service: Exact match on service ID\n- service_offering: Exact match on service offering ID\n- configuration_item: Exact match on configuration item ID\n- opened_by: Exact match on user who opened\n- status: Exact match on status (NEW, ASSESS, ROOT_CAUSE, FIX_IN_PROGRESS, RESOLVED, CLOSED)\n- category: Exact match on category (NETWORK, SOFTWARE, HARDWARE, DATABASE)\n- problem_statement: Partial match on problem statement\n- short_description: Partial match on short description\n- impact: Exact match on impact (HIGH, MEDIUM, LOW)\n- urgency: Exact match on urgency (HIGH, MEDIUM, LOW)\n- priority: Exact match on priority (CRITICAL, HIGH, MODERATE, LOW, PLANNING)\n- assigned_to: Exact match on assigned user\n- assignment_group: Exact match on assigned group\n- worknotes: Partial match on worknotes\n- workaround: Partial match on workaround\n- fix_notes: Partial match on fix notes\n- original_task: Exact match on original incident ID\n- created_after: Filter by created after datetime (ISO format)\n- created_before: Filter by created before datetime (ISO format)\n\nExample:\n{\n \"status\": \"NEW\",\n \"priority\": \"HIGH\"\n}\n\nReturns:\n{\n \"problems\": [...],\n \"total_count\": 5\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "problem_id": {
+ "type": "string",
+ "description": "Filter by problem ID"
+ },
+ "number": {
+ "type": "string",
+ "description": "Filter by number"
+ },
+ "service": {
+ "type": "string",
+ "description": "Filter by service ID"
+ },
+ "service_offering": {
+ "type": "string",
+ "description": "Filter by service offering ID"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Filter by configuration item ID"
+ },
+ "opened_by": {
+ "type": "string",
+ "description": "Filter by user who opened"
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by status (new, assess, root_cause, fix_in_progress, resolved, closed)"
+ },
+ "category": {
+ "type": "string",
+ "description": "Filter by category (network, software, hardware, database)"
+ },
+ "problem_statement": {
+ "type": "string",
+ "description": "Filter by problem statement (partial)"
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Filter by short description (partial)"
+ },
+ "impact": {
+ "type": "string",
+ "description": "Filter by impact (high, medium, low)"
+ },
+ "urgency": {
+ "type": "string",
+ "description": "Filter by urgency (high, medium, low)"
+ },
+ "priority": {
+ "type": "string",
+ "description": "Filter by priority (critical, high, moderate, low, planning)"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Filter by assigned user"
+ },
+ "assignment_group": {
+ "type": "string",
+ "description": "Filter by assigned group"
+ },
+ "worknotes": {
+ "type": "string",
+ "description": "Filter by worknotes (partial)"
+ },
+ "workaround": {
+ "type": "string",
+ "description": "Filter by workaround (partial)"
+ },
+ "fix_notes": {
+ "type": "string",
+ "description": "Filter by fix notes (partial)"
+ },
+ "original_task": {
+ "type": "string",
+ "description": "Filter by original incident ID"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter by created after (ISO datetime)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter by created before (ISO datetime)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_problems_assigned_to",
+ "title": null,
+ "description": "Get problems assigned to a specific user or group.\n\nCan filter by:\n- assignment_group: Group ID\n- assigned_to: User ID\n- Both (AND condition)\n\nExample:\n{\n \"assignment_group\": \"GROUP_004\"\n}\n\nOr:\n{\n \"assigned_to\": \"USER_007\"\n}\n\nOr both:\n{\n \"assignment_group\": \"GROUP_004\",\n \"assigned_to\": \"USER_007\"\n}\n\nReturns:\n{\n \"problems\": [...],\n \"total_count\": 3\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group": {
+ "type": "string",
+ "description": "Filter by assignment group ID"
+ },
+ "assigned_to": {
+ "type": "string",
+ "description": "Filter by assigned user ID"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_incident_by_number",
+ "title": null,
+ "description": "Retrieve an incident by its incident number.\n \n Use this tool to find a specific incident using its unique incident number.\n \n Parameters:\n - number (required): Incident number (e.g., INC-000001)\n \n Returns a single incident object if found, or an error if the incident doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "type": "string",
+ "description": "Incident number (e.g., INC-000001)"
+ }
+ },
+ "required": [
+ "number"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_incident_by_id",
+ "title": null,
+ "description": "Retrieve an incident by its incident ID.\n \n Use this tool to find a specific incident using its unique incident ID.\n \n Parameters:\n - incident_id (required): Incident's unique identifier\n \n Returns a single incident object if found, or an error if the incident doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "Incident's unique identifier"
+ }
+ },
+ "required": [
+ "incident_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_incidents",
+ "title": null,
+ "description": "List incidents with optional filters.\n \n Use this tool to retrieve a list of incidents. Without filters, returns all incidents.\n With filters, returns only incidents matching the specified criteria.\n \n Optional Filters:\n - incident_id: Filter by exact incident ID\n - number: Filter by exact incident number\n - service: Filter by service ID\n - service_offering: Filter by service offering ID\n - configuration_item: Filter by configuration item ID\n - called_id: Filter by caller ID\n - channel: Filter by channel (self-service, phone, email, chat, walk-in, virtual-agent)\n - status: Filter by status (new, in_progress, on_hold, resolved, closed, canceled)\n - category: Filter by category (inquiry-help, software, hardware, database, password-reset, network)\n - short_description: Filter by short description (partial match)\n - description: Filter by description (partial match)\n - impact: Filter by impact (high, medium, low)\n - urgency: Filter by urgency (high, medium, low)\n - priority: Filter by priority (critical, high, moderate, low, planning)\n - assigned_to: Filter by assigned user ID\n - assignment_group: Filter by assignment group ID\n - worknotes: Filter by worknotes (partial match)\n - resolution_notes: Filter by resolution notes (partial match)\n - close_notes: Filter by close notes (partial match)\n - resolution_code: Filter by resolution code\n - parent_incident: Filter by parent incident ID\n - problem: Filter by problem ID\n - change_request: Filter by change request ID\n - caused_by_change: Filter by caused by change ID\n - resolved_by: Filter by resolved by user ID\n - on_hold_reason: Filter by on hold reason\n - incident_template: Filter by incident template ID\n - resolved: Filter by resolved timestamp\n - created_after: Filter incidents created after date (ISO 8601 format)\n - created_before: Filter incidents created before date (ISO 8601 format)\n \n Returns a list of incident objects matching the filters, or all incidents if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by incident ID (exact match)"
+ },
+ "number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by incident number (exact match)"
+ },
+ "service": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by service ID"
+ },
+ "service_offering": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by service offering ID"
+ },
+ "configuration_item": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by configuration item ID"
+ },
+ "called_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by caller ID"
+ },
+ "channel": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by channel (self-service, phone, email, chat, walk-in, virtual-agent)",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent",
+ "web"
+ ]
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by status (new, in_progress, on_hold, resolved, closed, canceled)",
+ "enum": [
+ "new",
+ "in_progress",
+ "on_hold",
+ "resolved",
+ "closed",
+ "canceled"
+ ]
+ },
+ "category": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by category (inquiry-help, software, hardware, database, password-reset)",
+ "enum": [
+ "inquiry-help",
+ "software",
+ "hardware",
+ "database",
+ "password-reset",
+ "network"
+ ]
+ },
+ "short_description": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by short description (partial match)"
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by description (partial match)"
+ },
+ "impact": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by impact (high, medium, low)",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "urgency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by urgency (high, medium, low)",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "priority": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by priority (critical, high, moderate, low, planning)",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "assigned_to": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by assigned user ID"
+ },
+ "assignment_group": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by assignment group ID"
+ },
+ "worknotes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by worknotes (partial match)"
+ },
+ "resolution_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by resolution notes (partial match)"
+ },
+ "close_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by close notes (partial match)"
+ },
+ "resolution_code": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by resolution code",
+ "enum": [
+ "Duplicate",
+ "Known Error",
+ "No resolution provided",
+ "Resolved By Caller",
+ "Resolved By Problem",
+ "Resolved By Change",
+ "Solution Provided",
+ "Workaround Provided",
+ "User error"
+ ]
+ },
+ "parent_incident": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by parent incident ID"
+ },
+ "problem": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by problem ID"
+ },
+ "change_request": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by change request ID"
+ },
+ "caused_by_change": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by caused by change ID"
+ },
+ "resolved_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by resolved by user ID"
+ },
+ "on_hold_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by on hold reason",
+ "enum": [
+ "Awaiting Change",
+ "Awaiting Caller",
+ "Awaiting Problem"
+ ]
+ },
+ "incident_template": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by incident template ID"
+ },
+ "resolved": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by resolved timestamp"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter incidents created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter incidents created before this date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_incidents_assigned_to",
+ "title": null,
+ "description": "Find incidents that are assigned to a particular group or to a user.\n \n Use this tool to retrieve incidents assigned to a specific user or group.\n \n Note: This tool requires incident CRUD permissions. Reporter roles do not have access\n to this tool, and agent roles must have write permissions to incidents.\n \n Parameters:\n - assignment_group (optional): Group ID to filter by\n - assigned_to (optional): User ID to filter by\n \n Returns a list of incident objects assigned to the specified group or user.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Group ID to filter incidents by"
+ },
+ "assigned_to": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User ID to filter incidents by"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_incident",
+ "title": null,
+ "description": "Create a new incident in the system.\n \n Use this tool to create a new incident with the specified details.\n \n Required Parameters:\n - short_description: Brief description of the incident\n - caller_id: ID of the user who reported the incident\n \n Optional Parameters (all can be null/omitted):\n - service: Service ID related to the incident\n - service_offering: Service offering ID related to the incident\n - configuration_item: Configuration item ID related to the incident\n - channel: How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)\n - status: Current status of the incident (new, in_progress, on_hold, resolved, closed, canceled). Default: \"new\"\n - category: Category of the incident (inquiry-help, software, hardware, database, password-reset, network). Default: \"inquiry-help\"\n - description: Detailed description of the incident\n - impact: Impact level (high, medium, low). Default: \"low\"\n - urgency: Urgency level (high, medium, low). Default: \"low\"\n - priority: Priority level (critical, high, moderate, low, planning). Default: \"planning\"\n - assigned_to: User ID to assign the incident to\n - assignment_group: Group ID to assign the incident to\n - worknotes: Work notes for the incident\n - resolution_notes: Resolution notes for the incident\n - close_notes: Close notes for the incident\n - resolution_code: Resolution code for the incident\n - parent_incident: Parent incident ID if this is a child incident\n - problem: Problem ID related to the incident\n - change_request: Change request ID related to the incident\n - caused_by_change: Change ID that caused this incident\n - resolved_by: User ID who resolved the incident\n - on_hold_reason: Reason why the incident is on hold\n - incident_template: Incident template ID to use\n - resolved: Timestamp when the incident was resolved\n \n Default Values:\n When a parameter is null or omitted, the following defaults are applied:\n - status: \"new\"\n - category: \"inquiry-help\"\n - impact: \"low\"\n - urgency: \"low\"\n - priority: \"planning\"\n \n Auto-Generated Fields:\n - incident_id: Unique identifier for the incident (format: INC_001, INC_002, etc.)\n - number: Incident number (e.g., INC-000001)\n - created_at: Timestamp when the incident was created\n - updated_at: Timestamp when the incident was last updated\n \n Returns the newly created incident object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Service ID related to the incident"
+ },
+ "service_offering": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Service offering ID related to the incident"
+ },
+ "configuration_item": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Configuration item ID related to the incident"
+ },
+ "caller_id": {
+ "type": "string",
+ "description": "ID of the user who reported the incident"
+ },
+ "channel": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Current status of the incident. Default: 'new' if null or omitted",
+ "enum": [
+ "new",
+ "in_progress",
+ "on_hold",
+ "resolved",
+ "closed",
+ "canceled"
+ ]
+ },
+ "category": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Category of the incident. Default: 'inquiry-help' if null or omitted",
+ "enum": [
+ "inquiry-help",
+ "software",
+ "hardware",
+ "database",
+ "password-reset",
+ "network"
+ ]
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Brief description of the incident"
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Detailed description of the incident"
+ },
+ "impact": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Impact level. Default: 'low' if null or omitted",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "urgency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Urgency level. Default: 'low' if null or omitted",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "priority": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Priority level. Default: 'planning' if null or omitted",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "assigned_to": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User ID to assign the incident to"
+ },
+ "assignment_group": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Group ID to assign the incident to"
+ },
+ "worknotes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Work notes for the incident"
+ },
+ "resolution_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Resolution notes for the incident"
+ },
+ "close_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Close notes for the incident"
+ },
+ "resolution_code": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Resolution code for the incident",
+ "enum": [
+ "Duplicate",
+ "Known Error",
+ "No resolution provided",
+ "Resolved By Caller",
+ "Resolved By Problem",
+ "Resolved By Change",
+ "Solution Provided",
+ "Workaround Provided",
+ "User error"
+ ]
+ },
+ "parent_incident": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Parent incident ID if this is a child incident"
+ },
+ "problem": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Problem ID related to the incident"
+ },
+ "change_request": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Change request ID related to the incident"
+ },
+ "caused_by_change": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Change ID that caused this incident"
+ },
+ "resolved_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User ID who resolved the incident"
+ },
+ "on_hold_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Reason why the incident is on hold",
+ "enum": [
+ "Awaiting Change",
+ "Awaiting Caller",
+ "Awaiting Problem"
+ ]
+ },
+ "incident_template": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Incident template ID to use"
+ },
+ "resolved": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Timestamp when the incident was resolved (ISO 8601 format)"
+ }
+ },
+ "required": [
+ "caller_id",
+ "short_description"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_incident",
+ "title": null,
+ "description": "Update an existing incident in the system.\n \n Use this tool to update an existing incident with the specified details.\n \n Required Parameters:\n - incident_id: ID of the incident to update\n \n Optional Parameters:\n - number: Incident number\n - service: Service ID related to the incident\n - service_offering: Service offering ID related to the incident\n - configuration_item: Configuration item ID related to the incident\n - caller_id: ID of the user who reported the incident\n - channel: How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)\n - status: Current status of the incident (new, in_progress, on_hold, resolved, closed, canceled)\n - category: Category of the incident (inquiry-help, software, hardware, database, password-reset, network)\n - short_description: Brief description of the incident\n - description: Detailed description of the incident\n - impact: Impact level (high, medium, low)\n - urgency: Urgency level (high, medium, low)\n - priority: Priority level (critical, high, moderate, low, planning)\n - assigned_to: User ID to assign the incident to\n - assignment_group: Group ID to assign the incident to\n - worknotes: Work notes for the incident\n - resolution_notes: Resolution notes for the incident\n - close_notes: Close notes for the incident\n - resolution_code: Resolution code for the incident\n - parent_incident: Parent incident ID if this is a child incident\n - problem: Problem ID related to the incident\n - change_request: Change request ID related to the incident\n - caused_by_change: Change ID that caused this incident\n - resolved_by: User ID who resolved the incident\n - on_hold_reason: Reason why the incident is on hold\n - incident_template: Incident template ID to use\n - resolved: Timestamp when the incident was resolved\n \n Returns the updated incident object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "ID of the incident to update"
+ },
+ "number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Incident number"
+ },
+ "service": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Service ID related to the incident"
+ },
+ "service_offering": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Service offering ID related to the incident"
+ },
+ "configuration_item": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Configuration item ID related to the incident"
+ },
+ "caller_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "ID of the user who reported the incident"
+ },
+ "channel": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "How the incident was reported (self-service, phone, email, chat, walk-in, virtual-agent)",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent"
+ ]
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Current status of the incident",
+ "enum": [
+ "new",
+ "in_progress",
+ "on_hold",
+ "resolved",
+ "closed",
+ "canceled"
+ ]
+ },
+ "category": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Category of the incident",
+ "enum": [
+ "inquiry-help",
+ "software",
+ "hardware",
+ "database",
+ "password-reset",
+ "network"
+ ]
+ },
+ "short_description": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Brief description of the incident"
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Detailed description of the incident"
+ },
+ "impact": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Impact level",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "urgency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Urgency level",
+ "enum": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "priority": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Priority level",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "assigned_to": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User ID to assign the incident to"
+ },
+ "assignment_group": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Group ID to assign the incident to"
+ },
+ "worknotes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Work notes for the incident"
+ },
+ "resolution_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Resolution notes for the incident"
+ },
+ "close_notes": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Close notes for the incident"
+ },
+ "resolution_code": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Resolution code for the incident",
+ "enum": [
+ "Duplicate",
+ "Known Error",
+ "No resolution provided",
+ "Resolved By Caller",
+ "Resolved By Problem",
+ "Resolved By Change",
+ "Solution Provided",
+ "Workaround Provided",
+ "User error"
+ ]
+ },
+ "parent_incident": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Parent incident ID if this is a child incident"
+ },
+ "problem": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Problem ID related to the incident"
+ },
+ "change_request": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Change request ID related to the incident"
+ },
+ "caused_by_change": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Change ID that caused this incident"
+ },
+ "resolved_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "User ID who resolved the incident"
+ },
+ "on_hold_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Reason why the incident is on hold",
+ "enum": [
+ "Awaiting Change",
+ "Awaiting Caller",
+ "Awaiting Problem"
+ ]
+ },
+ "incident_template": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Incident template ID to use"
+ },
+ "resolved": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Timestamp when the incident was resolved (ISO 8601 format)"
+ }
+ },
+ "required": [
+ "incident_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_child_incidents",
+ "title": null,
+ "description": "List child incidents for a parent incident.\n \n Use this tool to retrieve all child incidents associated with a parent incident.\n \n Parameters:\n - parent_incident (required): Parent incident ID\n \n Returns a list of child incident mapping objects.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "parent_incident": {
+ "type": "string",
+ "description": "Parent incident ID"
+ }
+ },
+ "required": [
+ "parent_incident"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_parent_incident",
+ "title": null,
+ "description": "Find the parent incident for a child incident.\n \n Use this tool to retrieve the parent incident mapping for a child incident.\n \n Parameters:\n - child_incident (required): Child incident ID\n \n Returns the parent incident mapping object if found.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "child_incident": {
+ "type": "string",
+ "description": "Child incident ID"
+ }
+ },
+ "required": [
+ "child_incident"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_child_incident",
+ "title": null,
+ "description": "Add a child incident to a parent incident.\n \n Use this tool to create a parent-child relationship between two incidents.\n \n Parameters:\n - parent_incident (required): Parent incident ID\n - child_incident (required): Child incident ID\n \n Returns the child incident mapping object that was created.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "parent_incident": {
+ "type": "string",
+ "description": "Parent incident ID"
+ },
+ "child_incident": {
+ "type": "string",
+ "description": "Child incident ID"
+ }
+ },
+ "required": [
+ "parent_incident",
+ "child_incident"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_child_incidents",
+ "title": null,
+ "description": "Add multiple child incidents to a parent incident.\n \n Use this tool to create parent-child relationships between a parent incident and multiple child incidents.\n \n Parameters:\n - parent_incident (required): Parent incident ID\n - child_incidents (required): Array of child incident IDs\n \n Returns a list of child incident mapping objects that were created.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "parent_incident": {
+ "type": "string",
+ "description": "Parent incident ID"
+ },
+ "child_incidents": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Array of child incident IDs"
+ }
+ },
+ "required": [
+ "parent_incident",
+ "child_incidents"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_child_incident",
+ "title": null,
+ "description": "Update a child incident mapping.\n \n Use this tool to update an existing parent-child relationship between incidents.\n \n Parameters:\n - child_incident_mapping_id (required): ID of the child incident mapping to update\n - parent_incident (required): Parent incident ID\n - child_incident (required): Child incident ID\n \n Returns the updated child incident mapping object.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "child_incident_mapping_id": {
+ "type": "string",
+ "description": "ID of the child incident mapping to update"
+ },
+ "parent_incident": {
+ "type": "string",
+ "description": "Parent incident ID"
+ },
+ "child_incident": {
+ "type": "string",
+ "description": "Child incident ID"
+ }
+ },
+ "required": [
+ "child_incident_mapping_id",
+ "parent_incident",
+ "child_incident"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_child_incident",
+ "title": null,
+ "description": "Remove a child incident mapping.\n \n Use this tool to remove a parent-child relationship between incidents.\n \n Parameters (at least one required):\n - child_incident_mapping_id: ID of the child incident mapping to remove\n - parent_incident AND child_incident: Parent and child incident IDs to remove the mapping for\n \n Returns a boolean indicating success.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "child_incident_mapping_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "ID of the child incident mapping to remove"
+ },
+ "parent_incident": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Parent incident ID"
+ },
+ "child_incident": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Child incident ID"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "get_count_of_incident_priority_wise",
+ "title": null,
+ "description": "Get count of incidents grouped by priority.\n \n Returns an Object with priority as the key and the count of incidents which has that priority value\n as the value, for example {'critical': 5, 'low': 3}.\n \n Parameters:\n - priority_list (optional): Array of priorities to filter by (e.g., [\"critical\", \"high\", \"low\"])\n \n If a priority list is given in input then only those priorities will be considered for output.\n Empty string values in the array are ignored. All values must be valid Priority enum values.\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority_list": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "default": [],
+ "description": "Optional array of priorities to filter. Valid values: critical, high, moderate, low, planning. Empty strings are ignored."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_incident_for_assignment_group",
+ "title": null,
+ "description": "Count incidents for a specific assignment group with optional filters.\n \n Returns object where group id is the key and the number of incidents assigned to it is the count value.\n \n Parameters:\n - assignment_group_id (required): The assignment group ID to count incidents for\n - status (optional): Filter by incident status (new, in_progress, on_hold, resolved, closed, canceled)\n - priority (optional): Filter by incident priority (critical, high, moderate, low, planning)\n - channel (optional): Filter by incident channel (self-service, phone, email, chat, walk-in, virtual-agent, web)\n \n Optional fields are to support filtering to only find specific values.\n Empty string values are treated as no filter. All values must be valid enum values.\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "assignment_group_id": {
+ "type": "string",
+ "description": "The assignment group ID to count incidents for"
+ },
+ "status": {
+ "type": "string",
+ "default": "",
+ "description": "Optional status filter (new, in_progress, on_hold, resolved, closed, canceled)",
+ "enum": [
+ "new",
+ "in_progress",
+ "on_hold",
+ "resolved",
+ "closed",
+ "canceled"
+ ]
+ },
+ "priority": {
+ "type": "string",
+ "default": "",
+ "description": "Optional priority filter (critical, high, moderate, low, planning)",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low",
+ "planning"
+ ]
+ },
+ "channel": {
+ "type": "string",
+ "default": "",
+ "description": "Optional channel filter (self-service, phone, email, chat, walk-in, virtual-agent, web)",
+ "enum": [
+ "self-service",
+ "phone",
+ "email",
+ "chat",
+ "walk-in",
+ "virtual-agent",
+ "web"
+ ]
+ }
+ },
+ "required": [
+ "assignment_group_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_service_offerings",
+ "title": null,
+ "description": "List service offerings with optional filters. Returns all service offerings or filtered results.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_offering_id": {
+ "type": "string",
+ "description": "Filter by service offering ID (exact match)"
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by service offering name (partial match)"
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Filter by owner"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Filter by usage",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Filter by status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Filter by classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Filter by criticality",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Filter by short description (partial match)"
+ },
+ "parent": {
+ "type": "string",
+ "description": "Filter by parent service offering"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter service offerings created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter service offerings created before this date (ISO 8601 format)"
+ }
+ },
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_service_offering_by_name",
+ "title": null,
+ "description": "Find a service offering by its exact name. Returns the service offering details if found.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The exact name of the service offering to find"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "register_new_service_offering",
+ "title": null,
+ "description": "Register a new service offering to the system. Service offering name must be unique. Returns the newly created service offering object.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Service offering name",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Owner of the service offering"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Purpose/usage of the service offering",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Service offering status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Service offering classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Business criticality level",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Short description of the service offering",
+ "maxLength": 120
+ },
+ "parent": {
+ "type": "string",
+ "description": "Parent service offering ID"
+ }
+ },
+ "required": [
+ "name",
+ "owned_by",
+ "parent",
+ "short_description"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_service_offering",
+ "title": null,
+ "description": "Update service offering details. At least one field must be provided. Service offering name must be unique if provided. Returns error if all fields match current values (idempotency validation).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "service_offering_id": {
+ "type": "string",
+ "description": "Service offering's unique identifier"
+ },
+ "name": {
+ "type": "string",
+ "description": "Updated service offering name",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "Updated owner"
+ },
+ "used_for": {
+ "type": "string",
+ "description": "Updated usage/purpose",
+ "enum": [
+ "production",
+ "QA",
+ "test",
+ "development"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Updated status",
+ "enum": [
+ "operational",
+ "non-operational",
+ "repair_in_progress",
+ "ready",
+ "retired"
+ ]
+ },
+ "service_classification": {
+ "type": "string",
+ "description": "Updated classification",
+ "enum": [
+ "business",
+ "technology-management",
+ "application"
+ ]
+ },
+ "business_criticality": {
+ "type": "string",
+ "description": "Updated criticality",
+ "enum": [
+ "critical",
+ "somewhat-critical",
+ "less-critical",
+ "not-critical"
+ ]
+ },
+ "short_description": {
+ "type": "string",
+ "description": "Updated short description",
+ "maxLength": 120
+ },
+ "parent": {
+ "type": "string",
+ "description": "Updated parent service offering ID"
+ }
+ },
+ "required": [
+ "service_offering_id"
+ ],
+ "additionalProperties": false
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "retrieve_knowledge_articles",
+ "title": null,
+ "description": "List knowledge articles with optional filters.\n \n Use this tool to retrieve a list of knowledge articles. Without filters, returns all articles.\n With filters, returns only articles matching the specified criteria.\n \n Returns a list of knowledge article objects matching the filters with total_count, or all articles if no filters provided.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "string",
+ "description": "Filter by knowledge ID (exact match, e.g., KB_001)"
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Filter by KB number (exact match, e.g., KB0000001)"
+ },
+ "title": {
+ "type": "string",
+ "description": "Filter by title (partial match, case-insensitive)"
+ },
+ "body": {
+ "type": "string",
+ "description": "Filter by body content (partial match, case-insensitive)"
+ },
+ "state": {
+ "type": "string",
+ "description": "Filter by article state",
+ "enum": [
+ "draft",
+ "review",
+ "published",
+ "retired"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Filter by visibility level",
+ "enum": [
+ "internal",
+ "external"
+ ]
+ },
+ "owner_id": {
+ "type": "string",
+ "description": "Filter by owner user ID (exact match)"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Filter articles created after this date (ISO 8601 format)"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Filter articles created before this date (ISO 8601 format)"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "create_knowledge_article",
+ "title": null,
+ "description": "Create a new knowledge article in the system.\n \n Use this tool to add a new knowledge article with the specified details. The system automatically\n generates knowledge_id (KB_001, KB_002, etc.), kb_number (KB0000001, KB0000002, etc.), and timestamps.\n Returns the newly created knowledge article object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "Article title (required, 1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "body": {
+ "type": "string",
+ "description": "Full article content (detailed explanation, solutions, troubleshooting steps, etc.)"
+ },
+ "state": {
+ "type": "string",
+ "description": "Article state (defaults to 'published')",
+ "enum": [
+ "draft",
+ "review",
+ "published",
+ "retired"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Article visibility (defaults to 'internal')",
+ "enum": [
+ "internal",
+ "external"
+ ]
+ },
+ "owner_id": {
+ "type": "string",
+ "description": "User ID who owns the article (author/responsible person)"
+ }
+ },
+ "required": [
+ "title",
+ "owner_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_knowledge_article",
+ "title": null,
+ "description": "Update a knowledge article by either its knowledge_id OR kb_number.\n \n Use this tool to update one or more fields of a knowledge article. You can identify the article\n using either knowledge_id (e.g., KB_001) or kb_number (e.g., KB0000001). These are mutually\n exclusive identifiers - provide exactly one, not both.\n \n Returns the updated knowledge article object with all fields.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "knowledge_id": {
+ "type": "string",
+ "description": "Unique identifier of the article to update (e.g., KB_001). Mutually exclusive with kb_number - provide only one."
+ },
+ "kb_number": {
+ "type": "string",
+ "description": "Unique KB number of the article to update (e.g., KB0000001). Mutually exclusive with knowledge_id - provide only one."
+ },
+ "title": {
+ "type": "string",
+ "description": "Updated title (1-120 characters)",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "body": {
+ "type": "string",
+ "description": "Updated body content"
+ },
+ "state": {
+ "type": "string",
+ "description": "Updated state",
+ "enum": [
+ "draft",
+ "review",
+ "published",
+ "retired"
+ ]
+ },
+ "visibility": {
+ "type": "string",
+ "description": "Updated visibility",
+ "enum": [
+ "internal",
+ "external"
+ ]
+ },
+ "owner_id": {
+ "type": "string",
+ "description": "Updated owner user ID"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_incident_knowledge_links",
+ "title": null,
+ "description": "Find incident-knowledge links with optional filters. Returns list of incident knowledge links matching the criteria.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_kb_id": {
+ "type": "string",
+ "description": "Filter by incident knowledge link ID"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Filter by incident ID"
+ },
+ "knowledge_id": {
+ "type": "string",
+ "description": "Filter by knowledge article ID"
+ },
+ "used_as": {
+ "type": "string",
+ "description": "Filter by usage type(s). Can be a single value or comma-separated list of values (e.g., 'suggested,applied,resolution' or 'suggested, applied, resolution'). Valid values (lowercase only): suggested, applied, resolution. Returns links matching any of the specified values. Values must be provided in lowercase."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "link_knowledge_to_incident",
+ "title": null,
+ "description": "Link a knowledge article to an incident. Creates a new incident-knowledge link.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "Incident ID to link knowledge to"
+ },
+ "knowledge_id": {
+ "type": "string",
+ "description": "Knowledge article ID to link"
+ },
+ "used_as": {
+ "type": "string",
+ "description": "How the knowledge was used",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ]
+ }
+ },
+ "required": [
+ "incident_id",
+ "knowledge_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_knowledge_link_to_incident",
+ "title": null,
+ "description": "Remove a knowledge link from an incident. Can identify the link by incident_kb_id OR by combination of incident_id and knowledge_id.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_kb_id": {
+ "type": "string",
+ "description": "Incident knowledge link ID to remove"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Incident ID (must be used with knowledge_id)"
+ },
+ "knowledge_id": {
+ "type": "string",
+ "description": "Knowledge article ID (must be used with incident_id)"
+ },
+ "used_as": {
+ "type": "string",
+ "description": "Usage type to filter removal",
+ "enum": [
+ "suggested",
+ "applied",
+ "resolution"
+ ]
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "add_new_sla_definition",
+ "title": null,
+ "description": "Create a new SLA definition.\n\nAutomatically generates:\n- sla_def_id (SLA_001, SLA_002, ...)\n\nRequired fields:\n- name: Unique name for the SLA definition (<=120 chars)\n- metric: response or resolution\n- target_mins: Target time in minutes (>=1)\n- pause_on_pending: Boolean indicating if SLA pauses on pending status\n- active: Boolean indicating if the SLA definition is active\n\nOptional fields:\n- applies_to_priority: CRITICAL, HIGH, MODERATE, LOW\n- schedule: Schedule ID\n\nExample payload:\n{\n \"name\": \"Critical Response SLA\",\n \"metric\": \"RESPONSE\",\n \"target_mins\": 60,\n \"pause_on_pending\": true,\n \"active\": true,\n \"applies_to_priority\": \"CRITICAL\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition (unique, <=120 chars)"
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "SLA metric (response or resolution)"
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target time in minutes (>=1)",
+ "minimum": 1
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether to pause SLA on pending status"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the SLA definition is active"
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority this SLA applies to"
+ },
+ "schedule": {
+ "type": "string",
+ "description": "Schedule ID (<=32 chars)"
+ }
+ },
+ "required": [
+ "name",
+ "metric",
+ "target_mins",
+ "pause_on_pending",
+ "active"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_sla_definition",
+ "title": null,
+ "description": "Update an existing SLA definition by sla_def_id.\n\nAll fields are optional; only provided fields are updated.\nIf no changes are detected, the API returns an error.\n\nExample payload:\n{\n \"sla_def_id\": \"SLA_001\",\n \"target_mins\": 120,\n \"active\": false\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "string",
+ "description": "SLA definition ID (SLA_001, SLA_002, ...). Required when calling this tool."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition (unique, <=120 chars)"
+ },
+ "metric": {
+ "type": "string",
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "SLA metric"
+ },
+ "target_mins": {
+ "type": "integer",
+ "description": "Target time in minutes (>=1)",
+ "minimum": 1
+ },
+ "pause_on_pending": {
+ "type": "boolean",
+ "description": "Whether to pause SLA on pending status"
+ },
+ "active": {
+ "type": "boolean",
+ "description": "Whether the SLA definition is active"
+ },
+ "applies_to_priority": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Priority this SLA applies to"
+ },
+ "schedule": {
+ "type": "string",
+ "description": "Schedule ID (<=32 chars)"
+ }
+ },
+ "required": [
+ "sla_def_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_sla_definition_by_name",
+ "title": null,
+ "description": "Retrieve an SLA definition by its unique name.\n\nExample:\n{\n \"name\": \"Critical Response SLA\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the SLA definition"
+ }
+ },
+ "required": [
+ "name"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_sla_definitions",
+ "title": null,
+ "description": "List SLA definitions applying optional filters. Returns all SLA definitions if no filters provided.\n\nSupported filters (all optional):\n- sla_def_id, name\n- metric (RESPONSE, RESOLUTION)\n- target_mins, pause_on_pending, active\n- applies_to_priority (CRITICAL, HIGH, MODERATE, LOW)\n- created_after, created_before (ISO timestamp strings)\n\nNote:\n- Empty strings (\"\") or null values for parameters will return all results without filtering\n- For boolean fields (pause_on_pending, active), only use true/false to filter - null will return all results\n\nExample:\n{\n \"metric\": \"RESPONSE\",\n \"active\": true,\n \"applies_to_priority\": \"CRITICAL\"\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "sla_def_id": {
+ "type": "string",
+ "description": "Filter by sla_def_id"
+ },
+ "name": {
+ "type": "string",
+ "description": "Filter by name"
+ },
+ "metric": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "response",
+ "resolution"
+ ],
+ "description": "Filter by metric (response or resolution). Null returns all."
+ },
+ "target_mins": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Filter by target_mins"
+ },
+ "pause_on_pending": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Filter by pause_on_pending. Null returns all."
+ },
+ "applies_to_priority": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ],
+ "description": "Filter by applies_to_priority. Null returns all."
+ },
+ "active": {
+ "type": [
+ "boolean",
+ "null"
+ ],
+ "description": "Filter by active status. Null returns all."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "ISO timestamp: return SLA definitions created after this value"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "ISO timestamp: return SLA definitions created before this value"
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "total_sum_of_target_mins_per_priority",
+ "title": null,
+ "description": "Compute the total sum of target minutes grouped by priority.\n\nOptional arguments:\n- priority: Array of priorities to filter by (critical, high, moderate, low)\n\nReturns an object where keys are priorities and values are summed target minutes.\nExample response:\n{\n \"CRITICAL\": 120,\n \"HIGH\": 90,\n \"MODERATE\": 60\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ]
+ },
+ "description": "Optional list of priorities to filter by. Accepted values: critical, high, moderate, low."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "average_target_mins_per_priority",
+ "title": null,
+ "description": "Compute the average of target minutes grouped by priority.\n\nOptional arguments:\n- priority: Array of priorities to filter by (critical, high, moderate, low)\n\nReturns an object where keys are priorities and values are average target minutes.\nValues are rounded to 2 decimal places.\nExample response:\n{\n \"CRITICAL\": 45.5,\n \"HIGH\": 30.0\n}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "priority": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "critical",
+ "high",
+ "moderate",
+ "low"
+ ]
+ },
+ "description": "Optional list of priorities to filter by. Accepted values: critical, high, moderate, low."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_status",
+ "title": null,
+ "description": "Count notifications grouped by status.\n\nOptional arguments:\n- status: Array of statuses (queued, sent, delivered, opened, failed)\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "queued",
+ "sent",
+ "delivered",
+ "opened",
+ "failed"
+ ]
+ },
+ "description": "Optional array of statuses to filter by. Accepted values: queued, sent, delivered, opened, failed."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_incident",
+ "title": null,
+ "description": "Count notifications grouped by incident.\n\nOptional arguments:\n- incident_id: Array of incident IDs to filter by\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional array of incident IDs to limit the count."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "average_notifications_by_incident",
+ "title": null,
+ "description": "Calculate the average number of notifications per incident.\n\nOptional arguments:\n- incident_id: Array of incident IDs to limit the calculation\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional array of incident IDs."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "count_notifications_by_type",
+ "title": null,
+ "description": "Count notifications grouped by type.\n\nOptional arguments:\n- type: Array of notification types (report, update, alert, reminder, solution_proposal, other)\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "report",
+ "update",
+ "alert",
+ "reminder",
+ "solution_proposal",
+ "other"
+ ]
+ },
+ "description": "Optional array of notification types to filter by. Accepted values: report, update, alert, reminder, solution_proposal, other."
+ }
+ },
+ "required": []
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications_for_email",
+ "title": null,
+ "description": "Retrieve notifications sent to a specific email address.\n \n Use this tool to find all notifications that have been sent to a particular email address.\n \n Parameters:\n - email (required): Email address to search for\n \n Returns a list of notification objects if found, or an empty list if no notifications exist for the email.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "description": "Email address to search for"
+ }
+ },
+ "required": [
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications_sent_for_incident",
+ "title": null,
+ "description": "Retrieve notifications related to a specific incident.\n \n Use this tool to find all notifications that have been sent regarding a particular incident.\n \n Parameters:\n - incident_id (required): Incident ID to search for\n \n Returns a list of notification objects if found, or an empty list if no notifications exist for the incident.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "Incident ID to search for"
+ }
+ },
+ "required": [
+ "incident_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_notifications",
+ "title": null,
+ "description": "Search for notifications using various filter criteria.\n \n Use this tool to find notifications based on different filter parameters.\n All parameters below are optional, and you can search without providing any parameters to get all notifications.\n Empty string or null values for any parameter will be ignored in the search.\n \n Parameters:\n - notification_id (optional): Filter by notification ID\n - incident_id (optional): Filter by incident ID\n - email (optional): Filter by recipient email address\n - type (optional): Filter by notification type (alert, update, reminder, report, solution_proposal, other)\n - status (optional): Filter by notification status (queued, sent, delivered, opened, failed)\n - created_before (optional): Filter for notifications created before this timestamp (ISO format)\n - created_after (optional): Filter for notifications created after this timestamp (ISO format)\n \n Returns a list of notification objects that match the criteria.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification ID"
+ },
+ "incident_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by incident ID"
+ },
+ "email": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by recipient email address"
+ },
+ "type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification type",
+ "enum": [
+ "alert",
+ "update",
+ "reminder",
+ "report",
+ "solution_proposal",
+ "other"
+ ]
+ },
+ "status": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter by notification status",
+ "enum": [
+ "queued",
+ "sent",
+ "delivered",
+ "opened",
+ "failed"
+ ]
+ },
+ "created_before": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter for notifications created before this timestamp (ISO format)"
+ },
+ "created_after": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Filter for notifications created after this timestamp (ISO format)"
+ }
+ }
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "send_notification",
+ "title": null,
+ "description": "Create and send a new notification.\n \n Use this tool to create a new notification associated with an incident.\n \n Parameters:\n - incident_id (required): ID of the associated incident\n - email (required): Email address for notification delivery\n - type (optional): Type of notification (alert, update, reminder, report, solution_proposal, other)\n - status (optional): Status of notification (queued, sent, delivered, opened, failed)\n - subject (optional): Subject of the notification\n - message (optional): Message content of the notification\n \n Returns the created notification object.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "ID of the associated incident"
+ },
+ "email": {
+ "type": "string",
+ "description": "Email address for notification delivery"
+ },
+ "type": {
+ "type": "string",
+ "description": "Type of notification",
+ "enum": [
+ "alert",
+ "update",
+ "reminder",
+ "report",
+ "solution_proposal",
+ "other"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "Status of notification",
+ "enum": [
+ "queued",
+ "sent",
+ "delivered",
+ "opened",
+ "failed"
+ ],
+ "default": "queued"
+ },
+ "subject": {
+ "type": "string",
+ "description": "Subject of the notification"
+ },
+ "message": {
+ "type": "string",
+ "description": "Message content of the notification"
+ }
+ },
+ "required": [
+ "incident_id",
+ "email"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_notification",
+ "title": null,
+ "description": "Update an existing notification.\n \n Use this tool to update the properties of an existing notification.\n \n Parameters:\n - notification_id (required): ID of notification to update\n - incident_id (optional): New incident ID\n - email (optional): New email address\n - type (optional): New notification type (alert, update, reminder, report, solution_proposal, other)\n - status (optional): New notification status (queued, sent, delivered, opened, failed)\n - subject (optional): New subject\n - message (optional): New message content\n \n Returns the updated notification object, or an error if the notification doesn't exist.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "string",
+ "description": "ID of notification to update"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "New incident ID"
+ },
+ "email": {
+ "type": "string",
+ "description": "New email address"
+ },
+ "type": {
+ "type": "string",
+ "description": "New notification type",
+ "enum": [
+ "alert",
+ "update",
+ "reminder",
+ "report",
+ "solution_proposal",
+ "other"
+ ]
+ },
+ "status": {
+ "type": "string",
+ "description": "New notification status",
+ "enum": [
+ "queued",
+ "sent",
+ "delivered",
+ "opened",
+ "failed"
+ ]
+ },
+ "subject": {
+ "type": "string",
+ "description": "New subject"
+ },
+ "message": {
+ "type": "string",
+ "description": "New message content"
+ }
+ },
+ "required": [
+ "notification_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "delete_notifications",
+ "title": null,
+ "description": "Delete a notification by ID.\n \n Use this tool to delete a specific notification by its notification_id.\n The notification must belong to your organization.\n \n Parameters:\n - notification_id (required): The ID of the notification to delete (e.g., NOTIF_001)\n \n Returns a success message with the deleted notification ID.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "notification_id": {
+ "type": "string",
+ "description": "The ID of the notification to delete (e.g., NOTIF_001)"
+ }
+ },
+ "required": [
+ "notification_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "map_change_request",
+ "title": null,
+ "description": "Create a mapping between a change and either an incident or a problem.\n\nRequirements:\n- `change_id` is mandatory.\n- At least one of `incident_id` or `problem_id` must be provided (you can supply both to create parallel links).\n- The API automatically scopes the mapping to the caller's organization via headers.\n\nCommon uses:\n- Link an in-flight change to impacted incidents for traceability.\n- Associate a change with the problem it resolves.\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "change_id": {
+ "type": "string",
+ "description": "Change ID (e.g., CHG_001). Must belong to the caller's organization."
+ },
+ "incident_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Incident ID to link (optional if problem_id supplied)."
+ },
+ "problem_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Problem ID to link (optional if incident_id supplied)."
+ }
+ },
+ "required": [
+ "change_id"
+ ],
+ "anyOf": [
+ {
+ "required": [
+ "incident_id"
+ ]
+ },
+ {
+ "required": [
+ "problem_id"
+ ]
+ }
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_change_request_mappings",
+ "title": null,
+ "description": "List change mappings with powerful filters.\n\nAll parameters are optional; omitting filters returns every mapping within the caller's organization.\nUseful filters include change_id, incident_id, problem_id, and ISO timestamps for created_at windows.\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "change_request_mapping_id": {
+ "type": "string",
+ "description": "Exact mapping ID (CRM_###)."
+ },
+ "change_id": {
+ "type": "string",
+ "description": "Filter by change ID (CHG_###)."
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Filter by incident ID (INC_###)."
+ },
+ "problem_id": {
+ "type": "string",
+ "description": "Filter by problem ID (PRB_###)."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return mappings created on/after this ISO timestamp (e.g., 2024-02-10T09:00:00)."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return mappings created on/before this ISO timestamp."
+ }
+ }
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_change_request_mappings_for_incident",
+ "title": null,
+ "description": "Retrieve all mappings tied to a specific incident ID within the caller's org.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "Incident ID (INC_###) whose change mappings should be returned."
+ }
+ },
+ "required": [
+ "incident_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_change_request_mappings_for_problem",
+ "title": null,
+ "description": "Retrieve all mappings tied to a specific problem ID within the caller's org.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "problem_id": {
+ "type": "string",
+ "description": "Problem ID (PRB_###) whose change mappings should be returned."
+ }
+ },
+ "required": [
+ "problem_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "delete_change_request_mappings",
+ "title": null,
+ "description": "Delete change request mappings using precise filters with AND logic.\n\nThis tool deletes change request mappings based on filter criteria. It requires at least one\nfilter and uses AND logic when multiple filters are provided (all filters must match).\n\nSafety requirements:\n- You **must** provide at least one filter (`change_request_mapping_id`, `change_id`, `incident_id`, or `problem_id`).\n- If multiple filters are provided, ALL must match (AND logic) - this ensures precise deletion.\n- Prevents accidental bulk deletions by requiring all specified criteria to match.\n\nReturns:\n- deleted_count: Number of mappings deleted\n- deleted_mappings: List of deleted mapping objects with full details\n- message: Success message indicating what was deleted\n\nExamples:\n- Delete by mapping ID: {\"change_request_mapping_id\": \"CRM_001\"}\n- Delete by change and incident: {\"change_id\": \"CHG_001\", \"incident_id\": \"INC_001\"}\n- Delete by change only: {\"change_id\": \"CHG_001\"}\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "change_request_mapping_id": {
+ "type": "string",
+ "description": "Specific mapping ID (CRM_###)."
+ },
+ "change_id": {
+ "type": "string",
+ "description": "Delete mappings for this change."
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Delete mappings linked to this incident."
+ },
+ "problem_id": {
+ "type": "string",
+ "description": "Delete mappings linked to this problem."
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "change_request_mapping_id"
+ ]
+ },
+ {
+ "required": [
+ "change_id"
+ ]
+ },
+ {
+ "required": [
+ "incident_id"
+ ]
+ },
+ {
+ "required": [
+ "problem_id"
+ ]
+ }
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "link_affected_ci_to_incident",
+ "title": null,
+ "description": "Attach a configuration item to an incident, creating a TASKCI_xxx link.\n\nRequirements:\n- configuration_item: existing CI ID within the caller's organization\n- incident_id: existing incident ID within the same org\n",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "configuration_item": {
+ "type": "string",
+ "description": "CI identifier (e.g., CI_001)"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Incident identifier (e.g., INC_001)"
+ }
+ },
+ "required": [
+ "configuration_item",
+ "incident_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "list_incident_affected_cis",
+ "title": null,
+ "description": "List configuration items linked to incidents. All parameters optional.\nUse filters like incident_id or configuration_item to narrow the response, or created_before/after for time windows.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_affected_cis_id": {
+ "type": "string",
+ "description": "Specific mapping ID (TASKCI_###)."
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Filter by CI ID."
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Filter by incident ID."
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Return mappings created on/before this ISO timestamp."
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Return mappings created on/after this ISO timestamp."
+ }
+ }
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "remove_affected_ci_from_incident",
+ "title": null,
+ "description": "Delete incident-CI links. You must provide at least one filter (ID, incident_id, configuration_item, or date range).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_affected_cis_id": {
+ "type": "string",
+ "description": "Specific mapping ID to delete"
+ },
+ "configuration_item": {
+ "type": "string",
+ "description": "Remove mappings for this CI"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Remove mappings for this incident"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Delete mappings created on/before this ISO timestamp"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Delete mappings created on/after this ISO timestamp"
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "incident_affected_cis_id"
+ ]
+ },
+ {
+ "required": [
+ "configuration_item"
+ ]
+ },
+ {
+ "required": [
+ "incident_id"
+ ]
+ },
+ {
+ "required": [
+ "created_before"
+ ]
+ },
+ {
+ "required": [
+ "created_after"
+ ]
+ }
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_incident_slas",
+ "title": null,
+ "description": "List Incident SLA records with optional filters.\nAll parameters are optional; omitting them returns every incident SLA for the caller's organization.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_sla_id": {
+ "type": "string",
+ "description": "Filter by SLA record ID"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Filter by incident ID"
+ },
+ "sla_def_id": {
+ "type": "string",
+ "description": "Filter by SLA definition ID"
+ },
+ "stage": {
+ "type": "string",
+ "description": "Filter by stage (in_progress, paused, completed, cancelled, breached)"
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Filter by breach flag"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "ISO timestamp (<=) filter on created_on"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "ISO timestamp (>=) filter on created_on"
+ }
+ }
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "find_stage_wise_breached_incident_sla_counts",
+ "title": null,
+ "description": "Return the breached incident SLA counts grouped by stage.\nProvide an optional array of stages ([\"in_progress\", \"breached\", ...]) to limit the aggregation.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "stages": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Optional stage filters"
+ }
+ }
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "link_new_incident_sla",
+ "title": null,
+ "description": "Create a new Incident SLA record (incident_sla).\nRequires incident_id, sla_def_id, and start_time. Stage defaults to IN_PROGRESS.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_id": {
+ "type": "string",
+ "description": "Incident identifier"
+ },
+ "sla_def_id": {
+ "type": "string",
+ "description": "SLA definition identifier"
+ },
+ "stage": {
+ "type": "string",
+ "description": "Stage (in_progress, paused, completed, cancelled, breached)"
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Whether SLA has breached"
+ },
+ "start_time": {
+ "type": "string",
+ "description": "Start time (ISO timestamp)"
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "Breach time (ISO timestamp)"
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "Completion time (ISO timestamp)"
+ }
+ },
+ "required": [
+ "incident_id",
+ "sla_def_id",
+ "start_time"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "update_incident_sla_details",
+ "title": null,
+ "description": "Update an existing Incident SLA. Provide the incident_sla_id plus one or more fields to change.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_sla_id": {
+ "type": "string",
+ "description": "SLA record ID to update"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "New incident ID"
+ },
+ "sla_def_id": {
+ "type": "string",
+ "description": "New SLA definition ID"
+ },
+ "stage": {
+ "type": "string",
+ "description": "New stage (in_progress, paused, completed, cancelled, breached)"
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Update breach flag"
+ },
+ "start_time": {
+ "type": "string",
+ "description": "New start time (ISO timestamp)"
+ },
+ "breach_time": {
+ "type": "string",
+ "description": "New breach time (ISO timestamp)"
+ },
+ "completed_time": {
+ "type": "string",
+ "description": "New completion time (ISO timestamp)"
+ }
+ },
+ "required": [
+ "incident_sla_id"
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ },
+ {
+ "name": "delete_incident_slas",
+ "title": null,
+ "description": "Delete Incident SLA records filtered by identifiers or timestamps.\nAt least one filter is required (incident_sla_id, incident_id, sla_def_id, stage, has_breached, created_before, created_after).",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "incident_sla_id": {
+ "type": "string",
+ "description": "Specific record ID"
+ },
+ "incident_id": {
+ "type": "string",
+ "description": "Incident ID"
+ },
+ "sla_def_id": {
+ "type": "string",
+ "description": "SLA definition ID"
+ },
+ "stage": {
+ "type": "string",
+ "description": "Stage filter"
+ },
+ "has_breached": {
+ "type": "boolean",
+ "description": "Breach flag filter"
+ },
+ "created_before": {
+ "type": "string",
+ "description": "Created_on <= timestamp"
+ },
+ "created_after": {
+ "type": "string",
+ "description": "Created_on >= timestamp"
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "incident_sla_id"
+ ]
+ },
+ {
+ "required": [
+ "incident_id"
+ ]
+ },
+ {
+ "required": [
+ "sla_def_id"
+ ]
+ },
+ {
+ "required": [
+ "stage"
+ ]
+ },
+ {
+ "required": [
+ "has_breached"
+ ]
+ },
+ {
+ "required": [
+ "created_before"
+ ]
+ },
+ {
+ "required": [
+ "created_after"
+ ]
+ }
+ ]
+ },
+ "outputSchema": null,
+ "icons": null,
+ "annotations": null,
+ "meta": null,
+ "execution": null
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/data/tools/teams.json b/resources_servers/enterpriseops_gym/data/tools/teams.json
new file mode 100644
index 0000000000..cbddb0fb5e
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/data/tools/teams.json
@@ -0,0 +1,4590 @@
+{
+ "gym_name": "gym-teams-mcp",
+ "gym_url": "http://localhost:8002",
+ "snapshot_at": "2026-07-07T18:18:24.067935+00:00",
+ "tools": [
+ {
+ "name": "list_users",
+ "description": "List users in the organization.\n\n Retrieves a list of user objects following Microsoft Graph API v1.0 structure.\n Supports OData query parameters for filtering, sorting, pagination, and field selection.\n\n This endpoint corresponds to GET /users in Microsoft Graph API.\n\n OData Query Parameters:\n - _top: Optional. Number of items to return (1-999, default: 100)\n - _skip: Optional. Number of items to skip for pagination (\u22650, default: 0)\n - _filter: Optional. OData filter expression with support for:\n * Comparison operators: eq, ne, gt, lt, ge, le\n * String functions: startswith(), endswith(), contains()\n * Logical operators: and, or\n * Examples:\n - \"displayName eq 'Alice Johnson'\"\n - \"displayName eq 'Alice' or displayName eq 'Bob'\"\n - \"startswith(displayName,'A') and accountEnabled eq true\"\n - _orderby: Optional. OData orderby expression (e.g., \"displayName asc\")\n - _select: Optional. Comma-separated list of properties to return\n - _count: Optional. Include total count in response (true/False)\n\n Default Properties Returned:\n - businessPhones, displayName, givenName, id, jobTitle, mail,\n - mobilePhone, officeLocation, preferredLanguage, surname, userPrincipalName\n\n Response Structure:\n - Returns list of users with Microsoft Graph API v1.0 format:\n * @odata.context: Metadata context URL\n * @odata.count: Total count (if _count=true)\n * @odata.nextLink: Next page URL (if more results available)\n * value: Array of user objects\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Status Codes:\n - 200: Success - Users retrieved successfully\n - 400: Bad Request - Invalid query parameters\n - 401: Unauthorized - Invalid or missing access token\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_top": {
+ "type": "integer",
+ "description": "Number of items to return (1-999)",
+ "minimum": 1,
+ "maximum": 999,
+ "default": 100
+ },
+ "_skip": {
+ "type": "integer",
+ "description": "Number of items to skip for pagination",
+ "minimum": 0,
+ "default": 0
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression. Supports: eq, ne, gt, lt, ge, le operators; startswith(), endswith(), contains() functions; and, or logical operators. Examples: \"displayName eq 'Alice Johnson'\", \"displayName eq 'Alice' or displayName eq 'Bob'\", \"startswith(displayName,'A') and accountEnabled eq true\"",
+ "maxLength": 2000
+ },
+ "_orderby": {
+ "type": "string",
+ "description": "OData orderby expression (e.g., \"displayName asc\" or \"createdDateTime desc\")",
+ "maxLength": 500
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return (e.g., \"displayName,mail,jobTitle\")",
+ "maxLength": 1000
+ },
+ "_count": {
+ "type": "boolean",
+ "description": "Include total count in response",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "create_user",
+ "description": "Create a new user in the organization.\n\n Creates a new user following Microsoft Graph API v1.0 structure.\n This endpoint corresponds to POST /users in Microsoft Graph API.\n\n Request Body Requirements:\n - userPrincipalName: Required. User principal name in email format (max 320 characters)\n - displayName: Required. Display name of the user (max 256 characters)\n\n Optional Properties:\n - givenName: Given name/first name (max 128 characters)\n - surname: Surname/last name (max 128 characters)\n - jobTitle: Job title (max 128 characters)\n - mail: Primary email address (max 320 characters)\n - businessPhones: Array of business phone numbers\n - mobilePhone: Mobile phone number\n - officeLocation: Office location (max 128 characters)\n - preferredLanguage: Preferred language code (e.g., \"en-US\")\n\n Validation Rules:\n - userPrincipalName must be in email format (contain @)\n - userPrincipalName must be unique within the organization\n - displayName cannot be empty or whitespace only\n - All string fields will be trimmed of leading/trailing whitespace\n\n Response Structure:\n - Returns created user with Microsoft Graph API v1.0 format:\n * @odata.context: Metadata context URL\n * id: Unique user identifier (UUID)\n * userPrincipalName, displayName, and all provided properties\n * createdDateTime: Creation timestamp\n * Organizational metadata (orgId)\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Status Codes:\n - 201: Created - User created successfully\n - 400: Bad Request - Invalid user data or validation errors\n - 401: Unauthorized - Invalid or missing access token\n - 409: Conflict - User with same userPrincipalName already exists\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userPrincipalName": {
+ "type": "string",
+ "description": "User principal name in email format (e.g., john.doe@contoso.com)",
+ "minLength": 1,
+ "maxLength": 320,
+ "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user",
+ "minLength": 1,
+ "maxLength": 256
+ },
+ "accountEnabled": {
+ "type": "boolean",
+ "description": "Whether the account is enabled"
+ },
+ "mailNickname": {
+ "type": "string",
+ "description": "Mail alias (mailNickname)",
+ "minLength": 1,
+ "maxLength": 64
+ },
+ "passwordProfile": {
+ "type": "object",
+ "description": "Password profile settings",
+ "properties": {
+ "password": {
+ "type": "string",
+ "minLength": 1
+ },
+ "forceChangePasswordNextSignIn": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "password",
+ "forceChangePasswordNextSignIn"
+ ]
+ },
+ "givenName": {
+ "type": "string",
+ "description": "Given name (first name)",
+ "maxLength": 128
+ },
+ "surname": {
+ "type": "string",
+ "description": "Surname (last name)",
+ "maxLength": 128
+ },
+ "jobTitle": {
+ "type": "string",
+ "description": "Job title",
+ "maxLength": 128
+ },
+ "mail": {
+ "type": "string",
+ "description": "Primary email address",
+ "maxLength": 320,
+ "format": "email"
+ },
+ "businessPhones": {
+ "type": "array",
+ "description": "Business phone numbers",
+ "items": {
+ "type": "string",
+ "maxLength": 64
+ },
+ "maxItems": 10
+ },
+ "mobilePhone": {
+ "type": "string",
+ "description": "Mobile phone number",
+ "maxLength": 64
+ },
+ "officeLocation": {
+ "type": "string",
+ "description": "Office location",
+ "maxLength": 128
+ },
+ "preferredLanguage": {
+ "type": "string",
+ "description": "Preferred language code (e.g., en-US, fr-FR)",
+ "maxLength": 10,
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "department": {
+ "type": "string",
+ "description": "Department",
+ "maxLength": 128
+ },
+ "companyName": {
+ "type": "string",
+ "description": "Company name",
+ "maxLength": 128
+ },
+ "usageLocation": {
+ "type": "string",
+ "description": "Usage location (e.g., 'US')",
+ "maxLength": 10
+ },
+ "city": {
+ "type": "string",
+ "description": "City",
+ "maxLength": 128
+ },
+ "state": {
+ "type": "string",
+ "description": "State/Province",
+ "maxLength": 128
+ },
+ "country": {
+ "type": "string",
+ "description": "Country/Region",
+ "maxLength": 128
+ },
+ "streetAddress": {
+ "type": "string",
+ "description": "Street address",
+ "maxLength": 256
+ },
+ "postalCode": {
+ "type": "string",
+ "description": "Postal/ZIP code",
+ "maxLength": 64
+ },
+ "employeeId": {
+ "type": "string",
+ "description": "Employee identifier assigned by organization",
+ "maxLength": 16
+ },
+ "employeeType": {
+ "type": "string",
+ "description": "Worker type (e.g., Employee, Contractor, Consultant, Vendor)",
+ "maxLength": 128
+ },
+ "userType": {
+ "type": "string",
+ "description": "User classification (Member or Guest)",
+ "enum": [
+ "Member",
+ "Guest"
+ ],
+ "default": "Member"
+ },
+ "employeeHireDate": {
+ "type": "string",
+ "description": "Hire date in ISO 8601 format (e.g., 2024-01-15T00:00:00Z)",
+ "format": "date-time"
+ },
+ "otherMails": {
+ "type": "array",
+ "description": "Additional email addresses (max 250 entries, 250 chars each)",
+ "items": {
+ "type": "string",
+ "maxLength": 250,
+ "format": "email"
+ },
+ "maxItems": 250
+ },
+ "aboutMe": {
+ "type": "string",
+ "description": "Freeform text for user self-description"
+ },
+ "birthday": {
+ "type": "string",
+ "description": "User's birthday in ISO 8601 format (e.g., 1990-05-15T00:00:00Z)",
+ "format": "date-time"
+ },
+ "interests": {
+ "type": "array",
+ "description": "List of user interests",
+ "items": {
+ "type": "string"
+ }
+ },
+ "skills": {
+ "type": "array",
+ "description": "List of user skills",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mySite": {
+ "type": "string",
+ "description": "URL for user's personal website",
+ "maxLength": 512,
+ "format": "uri"
+ },
+ "preferredName": {
+ "type": "string",
+ "description": "User's preferred name",
+ "maxLength": 128
+ },
+ "faxNumber": {
+ "type": "string",
+ "description": "Fax number",
+ "maxLength": 64
+ },
+ "ageGroup": {
+ "type": "string",
+ "description": "Age group classification",
+ "enum": [
+ "Minor",
+ "NotAdult",
+ "Adult"
+ ]
+ },
+ "pastProjects": {
+ "type": "array",
+ "description": "List of past projects",
+ "items": {
+ "type": "string"
+ }
+ },
+ "responsibilities": {
+ "type": "array",
+ "description": "List of user responsibilities",
+ "items": {
+ "type": "string"
+ }
+ },
+ "schools": {
+ "type": "array",
+ "description": "List of schools attended",
+ "items": {
+ "type": "string"
+ }
+ },
+ "employeeOrgData": {
+ "type": "object",
+ "description": "Organization data (costCenter and division)",
+ "properties": {
+ "costCenter": {
+ "type": "string",
+ "description": "Cost center identifier"
+ },
+ "division": {
+ "type": "string",
+ "description": "Division name"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "userPrincipalName",
+ "displayName",
+ "accountEnabled",
+ "mailNickname",
+ "passwordProfile"
+ ]
+ }
+ },
+ {
+ "name": "get_user",
+ "description": "Retrieve a specific user by their ID or userPrincipalName.\n\n Returns user metadata following Microsoft Graph API v1.0 structure.\n This endpoint corresponds to GET /users/{id | userPrincipalName} in Microsoft Graph API.\n\n Request Parameters (at least one required):\n - userId: Optional. User identifier (UUID format)\n - userPrincipalName: Optional. User principal name (email format)\n\n Parameter Behavior:\n - If only 'userId' provided: Lookup user by ID\n - If only 'userPrincipalName' provided: Lookup user by UPN\n - If both provided: Validates they reference the same user, returns error if mismatch\n\n Optional Query Parameters:\n - _select: Comma-separated list of properties to return\n\n Supported ID Formats:\n - User ID (UUID): e.g., \"12345678-1234-1234-1234-123456789012\"\n - userPrincipalName: e.g., \"john.doe@contoso.com\"\n\n Response Structure:\n - Returns user with Microsoft Graph API v1.0 format:\n * @odata.context: Metadata context URL\n * id: Unique user identifier\n * userPrincipalName: User principal name\n * displayName: Display name\n * All available user properties (givenName, surname, jobTitle, mail, etc.)\n * createdDateTime: Creation timestamp\n * lastModifiedDateTime: Last modification timestamp\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Status Codes:\n - 200: Success - User retrieved successfully\n - 400: Bad Request - Invalid parameters or mismatch when both provided\n - 401: Unauthorized - Invalid or missing access token\n - 404: Not Found - User not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User identifier (UUID format). Either 'userId' or 'userPrincipalName' must be provided.",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "userPrincipalName": {
+ "type": "string",
+ "description": "User principal name in email format (e.g., 'alice.manager@techcorp.com'). Either 'userId' or 'userPrincipalName' must be provided.",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return (e.g., \"displayName,mail,jobTitle\")",
+ "maxLength": 1000
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "update_user",
+ "description": "Update user properties.\n\n Partially updates user metadata following Microsoft Graph API v1.0 structure.\n Only provided fields will be updated, others remain unchanged.\n This endpoint corresponds to PATCH /users/{id | userPrincipalName} in Microsoft Graph API.\n\n Request Parameters (at least one required):\n - userId: Optional. User identifier (UUID format)\n - userPrincipalName: Optional. User principal name (email format)\n \n Parameter Behavior:\n - If only 'userId' provided: Update user by ID\n - If only 'userPrincipalName' provided: Update user by UPN\n - If both provided: Validates they reference the same user, returns error if mismatch\n\n Updatable Properties (all optional):\n - displayName: Display name (max 256 characters)\n - givenName: Given name/first name (max 128 characters)\n - surname: Surname/last name (max 128 characters)\n - jobTitle: Job title (max 128 characters)\n - mail: Primary email address (max 320 characters)\n - businessPhones: Array of business phone numbers\n - mobilePhone: Mobile phone number\n - officeLocation: Office location (max 128 characters)\n - preferredLanguage: Preferred language code\n\n Update Rules:\n - At least one field must be provided for update\n - userPrincipalName cannot be updated (immutable)\n - Null values will clear optional fields\n - Empty strings will be treated as null for clearing\n - All string fields will be trimmed of leading/trailing whitespace\n\n Response Structure:\n - Returns updated user with Microsoft Graph API v1.0 format\n - Includes lastModifiedDateTime with current timestamp\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Status Codes:\n - 200: Success - User updated successfully\n - 400: Bad Request - No fields provided or invalid data\n - 401: Unauthorized - Invalid or missing access token\n - 404: Not Found - User not found\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User identifier - accepts either user ID (UUID) or userPrincipalName (e.g., 'alice_manager' or 'alice.manager@techcorp.com')",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "userPrincipalName": {
+ "type": "string",
+ "description": "User principal name in email format (e.g., 'alice.manager@techcorp.com'). Can be provided along with userId for validation.",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user",
+ "minLength": 1,
+ "maxLength": 256
+ },
+ "givenName": {
+ "type": "string",
+ "description": "Given name (first name) - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "surname": {
+ "type": "string",
+ "description": "Surname (last name) - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "jobTitle": {
+ "type": "string",
+ "description": "Job title - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "mail": {
+ "type": "string",
+ "description": "Primary email address - omit or use empty string to clear",
+ "maxLength": 320,
+ "format": "email"
+ },
+ "businessPhones": {
+ "type": "array",
+ "description": "Business phone numbers - omit or use empty array to clear",
+ "items": {
+ "type": "string",
+ "maxLength": 64
+ },
+ "maxItems": 10
+ },
+ "mobilePhone": {
+ "type": "string",
+ "description": "Mobile phone number - omit or use empty string to clear",
+ "maxLength": 64
+ },
+ "officeLocation": {
+ "type": "string",
+ "description": "Office location - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "preferredLanguage": {
+ "type": "string",
+ "description": "Preferred language code - omit or use empty string to clear",
+ "maxLength": 10,
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "accountEnabled": {
+ "type": "boolean",
+ "description": "Account enabled state (true/false). Omit to leave unchanged."
+ },
+ "mailNickname": {
+ "type": "string",
+ "description": "Mail alias (mailNickname) - omit or use empty string to clear",
+ "maxLength": 64
+ },
+ "department": {
+ "type": "string",
+ "description": "Department - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "companyName": {
+ "type": "string",
+ "description": "Company name - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "usageLocation": {
+ "type": "string",
+ "description": "Usage location (e.g., 'US') - omit or use empty string to clear",
+ "maxLength": 10
+ },
+ "city": {
+ "type": "string",
+ "description": "City - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "state": {
+ "type": "string",
+ "description": "State/Province - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "country": {
+ "type": "string",
+ "description": "Country/Region - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "streetAddress": {
+ "type": "string",
+ "description": "Street address - omit or use empty string to clear",
+ "maxLength": 256
+ },
+ "postalCode": {
+ "type": "string",
+ "description": "Postal/ZIP code - omit or use empty string to clear",
+ "maxLength": 64
+ },
+ "employeeId": {
+ "type": "string",
+ "description": "Employee identifier - omit or use empty string to clear",
+ "maxLength": 16
+ },
+ "employeeType": {
+ "type": "string",
+ "description": "Worker type - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "userType": {
+ "type": "string",
+ "description": "User classification (Member or Guest) - omit to leave unchanged. Note: Cannot be set to null via API.",
+ "enum": [
+ "Member",
+ "Guest"
+ ]
+ },
+ "employeeHireDate": {
+ "type": "string",
+ "description": "Hire date - omit or use empty string to clear",
+ "format": "date-time"
+ },
+ "otherMails": {
+ "type": "array",
+ "description": "Additional email addresses - omit or use empty array to clear",
+ "items": {
+ "type": "string",
+ "maxLength": 250
+ },
+ "maxItems": 250
+ },
+ "aboutMe": {
+ "type": "string",
+ "description": "Self-description - omit or use empty string to clear"
+ },
+ "birthday": {
+ "type": "string",
+ "description": "Birthday - omit or use empty string to clear",
+ "format": "date-time"
+ },
+ "interests": {
+ "type": "array",
+ "description": "Interests - omit or use empty array to clear",
+ "items": {
+ "type": "string"
+ }
+ },
+ "skills": {
+ "type": "array",
+ "description": "Skills - omit or use empty array to clear",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mySite": {
+ "type": "string",
+ "description": "Personal website - omit or use empty string to clear",
+ "maxLength": 512
+ },
+ "preferredName": {
+ "type": "string",
+ "description": "Preferred name - omit or use empty string to clear",
+ "maxLength": 128
+ },
+ "faxNumber": {
+ "type": "string",
+ "description": "Fax number - omit or use empty string to clear",
+ "maxLength": 64
+ },
+ "ageGroup": {
+ "type": "string",
+ "description": "Age group classification - omit to leave unchanged",
+ "enum": [
+ "Minor",
+ "NotAdult",
+ "Adult"
+ ]
+ },
+ "isResourceAccount": {
+ "type": "boolean",
+ "description": "Resource account flag - omit to leave unchanged"
+ },
+ "pastProjects": {
+ "type": "array",
+ "description": "Past projects - omit or use empty array to clear",
+ "items": {
+ "type": "string"
+ }
+ },
+ "responsibilities": {
+ "type": "array",
+ "description": "Responsibilities - omit or use empty array to clear",
+ "items": {
+ "type": "string"
+ }
+ },
+ "schools": {
+ "type": "array",
+ "description": "Schools attended - omit or use empty array to clear",
+ "items": {
+ "type": "string"
+ }
+ },
+ "employeeOrgData": {
+ "type": "object",
+ "description": "Organization data - omit to leave unchanged, provide empty object {} to clear",
+ "properties": {
+ "costCenter": {
+ "type": "string"
+ },
+ "division": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "required": [],
+ "minProperties": 2
+ }
+ },
+ {
+ "name": "delete_user",
+ "description": "Delete a user by ID or userPrincipalName.\n\n Deletes a user following Microsoft Graph API v1.0 behavior.\n By default, performs soft delete (user marked as deleted but preserved).\n This endpoint corresponds to DELETE /users/{id | userPrincipalName} in Microsoft Graph API.\n\n Request Parameters (at least one required):\n - userId: Optional. User identifier (UUID format)\n - userPrincipalName: Optional. User principal name (email format)\n\n Parameter Behavior:\n - If only 'userId' provided: Delete user by ID\n - If only 'userPrincipalName' provided: Delete user by UPN\n - If both provided: Validates they reference the same user, returns error if mismatch\n\n Delete Behavior:\n - Soft Delete (default): User is marked as deleted but data is preserved\n - User will no longer appear in regular queries or authentication\n - Soft-deleted users can potentially be restored\n - Associated data (chats, etc.) is preserved but inaccessible\n\n Cascade Effects:\n - User access is immediately revoked\n - User will not appear in user lists or searches\n - Associated organizational relationships are updated\n\n Response:\n - Returns 204 No Content on successful deletion\n - No response body as per Microsoft Graph API v1.0\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Status Codes:\n - 204: No Content - User deleted successfully\n - 400: Bad Request - Invalid parameters or mismatch when both provided\n - 401: Unauthorized - Invalid or missing access token\n - 404: Not Found - User not found or already deleted\n - 500: Internal Server Error",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User identifier (UUID format). Either 'userId' or 'userPrincipalName' must be provided.",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "userPrincipalName": {
+ "type": "string",
+ "description": "User principal name in email format (e.g., 'alice.manager@techcorp.com'). Either 'userId' or 'userPrincipalName' must be provided.",
+ "minLength": 1,
+ "maxLength": 320
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "create_chat",
+ "description": "Create a new chat (one-on-one or group) following Microsoft Graph API v1.0 specification.\n\n API Endpoint: POST /chats\n\n Microsoft Graph API Permissions:\n - Delegated (work or school account): Chat.Create (least privileged), Chat.ReadWrite (higher privileged)\n - Delegated (personal Microsoft account): Not supported\n - Application: Chat.Create (least privileged)\n\n Important Notes:\n - Only one one-on-one chat can exist between two members. If a one-on-one chat already exists, this operation returns the existing chat and doesn't create a new one.\n - For delegated permissions, the authenticated user MUST be included in the members list\n - For application permissions, no membership requirement\n - This API does NOT require user_id parameter as it operates directly on the /chats resource\n\n Reference: https://learn.microsoft.com/en-us/graph/api/chat-post",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatType": {
+ "type": "string",
+ "enum": [
+ "oneOnOne",
+ "group"
+ ],
+ "description": "Type of chat to create: 'oneOnOne' or 'group'"
+ },
+ "topic": {
+ "type": "string",
+ "description": "Chat topic/title. Optional for oneOnOne (must be null), required for group chats. Maximum 255 characters.",
+ "maxLength": 255
+ },
+ "members": {
+ "type": "array",
+ "description": "List of conversation members. Each member must include _odata_type, roles, and user_odata_bind. Minimum 2 members required.",
+ "minItems": 2,
+ "items": {
+ "type": "object",
+ "properties": {
+ "_odata_type": {
+ "type": "string",
+ "description": "OData type - must be '#microsoft.graph.aadUserConversationMember'",
+ "default": "#microsoft.graph.aadUserConversationMember"
+ },
+ "roles": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "guest"
+ ]
+ },
+ "description": "Roles assigned to the member. In-tenant guest users must be assigned 'guest' role. Out-of-tenant external users must be assigned 'owner' role."
+ },
+ "user_odata_bind": {
+ "type": "string",
+ "description": "URL to user resource. Format: 'https://graph.microsoft.com/v1.0/users('user-id')' or 'https://graph.microsoft.com/v1.0/users('user-principal-name')'"
+ },
+ "tenantId": {
+ "type": "string",
+ "description": "Tenant ID for federated users (external users from another organization)"
+ }
+ },
+ "required": [
+ "_odata_type",
+ "roles",
+ "user_odata_bind"
+ ]
+ }
+ },
+ "installedApps": {
+ "type": "array",
+ "description": "Apps to install in the chat during creation (optional)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "teamsApp_odata_bind": {
+ "type": "string",
+ "description": "URL to teams app resource. Format: 'https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/app-id'"
+ },
+ "consentedPermissionSet": {
+ "type": "object",
+ "description": "Consented permission set with RSC (Resource-Specific Consent) permissions (optional)",
+ "properties": {
+ "resourceSpecificPermissions": {
+ "type": "array",
+ "description": "List of resource-specific permissions",
+ "items": {
+ "type": "object",
+ "properties": {
+ "permissionValue": {
+ "type": "string",
+ "description": "Permission value (e.g., 'ChatMessage.Read.Chat', 'OnlineMeeting.ReadBasic.Chat')"
+ },
+ "permissionType": {
+ "type": "string",
+ "enum": [
+ "application",
+ "delegated"
+ ],
+ "description": "Permission type: 'application' or 'delegated'"
+ }
+ },
+ "required": [
+ "permissionValue",
+ "permissionType"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "teamsApp_odata_bind"
+ ]
+ }
+ }
+ },
+ "required": [
+ "chatType",
+ "members"
+ ]
+ }
+ },
+ {
+ "name": "update_chat",
+ "description": "Update a chat's properties (currently only topic is supported). Only group chats can be updated.\n\n API Endpoint: PATCH /chats/{chat-id}\n\n This API does NOT require user_id parameter as it operates directly on the chat resource.\n\n Reference: https://learn.microsoft.com/en-us/graph/api/chat-patch",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "topic": {
+ "type": "string",
+ "description": "Chat topic/title to update",
+ "maxLength": 250
+ }
+ },
+ "required": [
+ "chatId",
+ "topic"
+ ]
+ }
+ },
+ {
+ "name": "list_chats",
+ "description": "List chats for the authenticated user (Microsoft Graph API compliant).\n\n API Endpoint: GET /chats\n\n Microsoft Graph API Permissions:\n - Delegated (work or school account): Chat.Read (least privileged), Chat.ReadWrite (higher privileged)\n - Delegated (personal Microsoft account): Not supported\n - Application: Chat.Read.All (least privileged), Chat.ReadWrite.All (higher privileged)\n\n Microsoft Graph API Query Parameters (EXACT from documentation):\n\n Name: $expand\n Description: Currently supports members and lastMessagePreview properties.\n \n Name: $top\n Description: Controls the number of items per response. Maximum allowed $top value is 50.\n \n Name: $filter\n Description: Filters results.\n \n Name: $orderby\n Description: Currently supports lastMessagePreview/createdDateTime in descending order. Ascending order is currently not supported.\n\n Reference: https://learn.microsoft.com/en-us/graph/api/chat-list?view=graph-rest-1.0&tabs=http",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_expand": {
+ "type": "string",
+ "description": "Expand related entities. Currently supports 'members' and 'lastMessagePreview' properties. Example: 'members' or 'lastMessagePreview' or 'members,lastMessagePreview'"
+ },
+ "_top": {
+ "type": "integer",
+ "description": "Controls the number of items per response. Maximum allowed $top value is 50 per Microsoft Graph API specification.",
+ "default": 50,
+ "minimum": 1,
+ "maximum": 50
+ },
+ "_filter": {
+ "type": "string",
+ "description": "Filters results. OData filter expression for filtering chat results."
+ },
+ "_orderby": {
+ "type": "string",
+ "description": "Sort order. Currently supports 'lastMessagePreview/createdDateTime desc' only. Ascending order is NOT supported per Microsoft Graph API. Example: 'lastMessagePreview/createdDateTime desc'"
+ }
+ }
+ }
+ },
+ {
+ "name": "list_chat_messages",
+ "description": "List messages in a chat (Microsoft Graph API compliant).\n\n API Endpoint: GET /chats/{chat-id}/messages\n API Endpoint (with user context): GET /users/{user-id}/chats/{chat-id}/messages\n\n Microsoft Graph API Permissions:\n - Delegated (work or school account): Chat.Read (least privileged), Chat.ReadWrite (higher privileged)\n * Allows accessing YOUR OWN chats only (requires chat membership)\n * userId parameter is NOT required (uses authenticated user)\n - Application: ChatMessage.Read.Chat (least privileged), Chat.Read.All, Chat.ReadWrite.All (higher privileged)\n * Allows accessing ANY chat without membership requirement\n * userId parameter is REQUIRED to specify which user's context to operate in\n * Must use endpoint: /users/{user_id}/chats/{chat_id}/messages\n\n IMPORTANT CONSTRAINTS:\n 1. Delegated permissions (Chat.Read, Chat.ReadWrite):\n - User can ONLY list messages from their own chats (membership required)\n - userId parameter should NOT be provided\n 2. Application permissions (ChatMessage.Read.Chat, Chat.Read.All, Chat.ReadWrite.All):\n - Can list messages from ANY chat without membership requirement\n - userId parameter is REQUIRED (to specify user context)\n - Returns 400 Bad Request if userId is missing\n\n Microsoft Graph API Query Parameters (EXACT from documentation):\n \n Name: $top\n - Controls the number of items per response\n - Maximum allowed $top value is 50\n \n Name: $orderby\n - Currently supports the lastModifiedDateTime (default) and createdDateTime properties in descending order\n - The ascending order is currently not supported\n - Valid values: \"lastModifiedDateTime desc\" (default), \"createdDateTime desc\"\n \n Name: $filter\n - Sets the date range filter for the lastModifiedDateTime and createdDateTime properties\n - The lastModifiedDateTime property supports the gt and lt operators\n - The createdDateTime property supports the lt operator\n - You can only filter results if the request URL contains the $orderby and $filter query parameters configured for the same property; otherwise, the $filter query option is ignored\n - Valid filter formats:\n * For lastModifiedDateTime: \"lastModifiedDateTime gt {datetime}\" or \"lastModifiedDateTime lt {datetime}\" or both with \"and\"\n * For createdDateTime: \"createdDateTime lt {datetime}\"\n \n Reference: https://learn.microsoft.com/en-us/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "userId": {
+ "type": "string",
+ "description": "User identifier (user ID or user principal name). REQUIRED for application permissions to specify which user's context to operate in. NOT required for delegated permissions (uses authenticated user automatically). Example: 'alice_manager' or 'alice.manager@techcorp.com'"
+ },
+ "_top": {
+ "type": "integer",
+ "description": "Controls the number of items per response. Maximum allowed value is 50 per Microsoft Graph API specification.",
+ "minimum": 1,
+ "maximum": 50,
+ "default": 20
+ },
+ "_orderby": {
+ "type": "string",
+ "description": "Sort order. ONLY supports 'lastModifiedDateTime desc' (default) or 'createdDateTime desc'. Ascending order is NOT supported per Microsoft Graph API.",
+ "enum": [
+ "lastModifiedDateTime desc",
+ "createdDateTime desc"
+ ],
+ "default": "lastModifiedDateTime desc"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "Date range filter. MUST match the property in _orderby parameter. Format: 'lastModifiedDateTime gt {ISO8601}' and/or 'lastModifiedDateTime lt {ISO8601}' OR 'createdDateTime lt {ISO8601}'. The lastModifiedDateTime property supports gt and lt operators. The createdDateTime property supports ONLY lt operator. Filter is IGNORED if _orderby and _filter use different properties. Examples: 'lastModifiedDateTime gt 2021-01-01T00:00:00.000Z and lastModifiedDateTime lt 2021-12-31T23:59:59.999Z' (when _orderby='lastModifiedDateTime desc'), 'createdDateTime lt 2021-12-31T23:59:59.999Z' (when _orderby='createdDateTime desc')"
+ }
+ },
+ "required": [
+ "chatId"
+ ]
+ }
+ },
+ {
+ "name": "add_tab_to_chat",
+ "description": "Add (pin) a tab to the specified chat.\n\n Creates a new tab in a chat following Microsoft Graph API v1.0 structure.\n The corresponding app must already be installed in the chat.\n This endpoint corresponds to POST /chats/{chat-id}/tabs in Microsoft Graph API.\n Provide teamsApp_odata_bind; it may be a full URL, short 'teamsApps/{id}', or a bare app ID.\n\n API Endpoint: POST /chats/{chat_id}/tabs",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier where the tab will be added",
+ "minLength": 1
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Name of the tab",
+ "minLength": 1,
+ "maxLength": 256
+ },
+ "teamsApp_odata_bind": {
+ "type": "string",
+ "description": "Teams app reference. Must be full Microsoft Graph URL: https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/{app-id}",
+ "minLength": 1,
+ "pattern": "^https://graph\\.microsoft\\.com/v1\\.0/appCatalogs/teamsApps/[a-zA-Z0-9-]+$"
+ },
+ "configuration": {
+ "type": "object",
+ "description": "Container for custom settings applied to a tab",
+ "properties": {
+ "entityId": {
+ "type": "string",
+ "description": "Identifier for the entity hosted by the tab provider"
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL used for rendering tab contents in Teams"
+ },
+ "removeUrl": {
+ "type": "string",
+ "description": "URL called by Teams client when tab is removed"
+ },
+ "websiteUrl": {
+ "type": "string",
+ "description": "URL for showing tab contents outside of Teams"
+ }
+ }
+ }
+ },
+ "required": [
+ "chatId",
+ "displayName",
+ "teamsApp_odata_bind"
+ ]
+ }
+ },
+ {
+ "name": "send_chat_message",
+ "description": "Send a new message in a chat (Microsoft Graph API compliant). API Endpoint: POST /chats/{chat_id}/messages.\n\n Microsoft Graph API Permissions (exact from documentation):\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | ChatMessage.Send | Chat.ReadWrite, Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | Teamwork.Migrate.All | Not available\n\n Important: \"This API can't create a new chat; you must use the list chats method to retrieve the ID of an existing chat before you can create a chat message.\"\n\n Terms of use: \"It is a violation of the terms of use to use Microsoft Teams as a log file. Only send messages that people will read.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "body": {
+ "type": "object",
+ "description": "Message body content (required). Plaintext/HTML representation of the content of the chat message. Representation is specified by the contentType inside the body. The content is always in HTML if the chat message contains a chatMessageMention.",
+ "properties": {
+ "content": {
+ "type": "string",
+ "description": "The content of the message"
+ },
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "Content type of the message",
+ "default": "text"
+ }
+ },
+ "required": [
+ "content"
+ ]
+ },
+ "replyToId": {
+ "type": "string",
+ "description": "Read-only. ID of the parent chat message or root chat message of the thread. (Only applies to chat messages in channels, not chats.)"
+ },
+ "subject": {
+ "type": "string",
+ "description": "Subject of the message, in plaintext (optional)"
+ },
+ "summary": {
+ "type": "string",
+ "description": "Summary text of the chat message that could be used for push notifications and summary views or fall back views. Only applies to channel chat messages, not chat messages in a chat."
+ },
+ "importance": {
+ "type": "string",
+ "enum": [
+ "normal",
+ "high",
+ "urgent"
+ ],
+ "description": "The importance of the chat message. The possible values are: normal, high, urgent.",
+ "default": "normal"
+ },
+ "locale": {
+ "type": "string",
+ "description": "Locale of the chat message set by the client. Always set to en-us.",
+ "default": "en-us"
+ },
+ "attachments": {
+ "type": "array",
+ "description": "References to attached objects like files, tabs, meetings etc.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Read-only. Unique id of the attachment."
+ },
+ "contentType": {
+ "type": "string",
+ "description": "The media type of the content attachment. It can have the following values: reference, file, card."
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL for the content of the attachment. Supported protocols: http, https, file and data."
+ },
+ "content": {
+ "type": "string",
+ "description": "The content of the attachment. If the attachment is a rich card, set the property to the rich card object. This property and contentUrl are mutually exclusive."
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the attachment."
+ },
+ "thumbnailUrl": {
+ "type": "string",
+ "description": "URL to a thumbnail image that the channel can use if it supports using an alternative, smaller form of content or contentUrl. For example, if you set contentType to application/word and set contentUrl to the location of the Word document, you might include a thumbnail image that represents the document. The channel could display the thumbnail image instead of the document. When the user clicks the image, the channel would open the document."
+ },
+ "teamsAppId": {
+ "type": "string",
+ "description": "The ID of the Teams app that is associated with the attachment. The property is used to attribute a Teams message card to the specified app."
+ }
+ }
+ }
+ },
+ "mentions": {
+ "type": "array",
+ "description": "List of entities mentioned in the chat message. Supported entities are: user, bot, team, channel, chat, and tag.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "description": "Index of an entity being mentioned in the specified chatMessage. Matches the {index} value in the corresponding tag in the message body."
+ },
+ "mentionText": {
+ "type": "string",
+ "description": "String used to represent the mention. For example, a user's display name, a team name."
+ },
+ "mentioned": {
+ "type": "object",
+ "description": "The entity (user, application, team, or channel) that was @mentioned.",
+ "properties": {
+ "user": {
+ "type": "object",
+ "description": "If a user is mentioned, this property contains the user details.",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "ID of the user."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user."
+ },
+ "userIdentityType": {
+ "type": "string",
+ "enum": [
+ "aadUser",
+ "onPremiseAadUser",
+ "anonymousGuest",
+ "federatedUser"
+ ],
+ "description": "Type of user identity. The possible values are: aadUser, onPremiseAadUser, anonymousGuest, federatedUser, personalMicrosoftAccountUser, skypeUser, phoneUser, unknownFutureValue and emailUser."
+ }
+ }
+ },
+ "application": {
+ "type": "object",
+ "description": "If an application is mentioned, this property contains the application details.",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "applicationIdentityType": {
+ "type": "string"
+ }
+ }
+ },
+ "conversation": {
+ "type": "object",
+ "description": "If a conversation (team/channel) is mentioned, this property contains the conversation details.",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "conversationIdentityType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "channelIdentity": {
+ "type": "object",
+ "description": "If the message was sent in a channel, represents identity of the channel. This property is null for chat messages.",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "The identity of the team in which the channel is located."
+ },
+ "channelId": {
+ "type": "string",
+ "description": "The identity of the channel in which the message was posted."
+ }
+ }
+ },
+ "policyViolation": {
+ "type": "object",
+ "description": "Defines the properties of a policy violation set by a data loss prevention (DLP) application.",
+ "properties": {
+ "dlpAction": {
+ "type": "string",
+ "enum": [
+ "none",
+ "notifySender",
+ "blockAccess",
+ "blockAccessExternal"
+ ],
+ "description": "The action taken by the DLP provider on the message. Supported values are: none, notifySender, blockAccess, blockAccessExternal."
+ },
+ "justificationText": {
+ "type": "string",
+ "description": "Justification text provided by the sender of the message when overriding a policy violation."
+ },
+ "policyTip": {
+ "type": "object",
+ "description": "Information to display to the message sender about why the message was flagged as a violation.",
+ "properties": {
+ "generalText": {
+ "type": "string"
+ },
+ "complianceUrl": {
+ "type": "string"
+ },
+ "matchedConditionDescriptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "userAction": {
+ "type": "string",
+ "enum": [
+ "none",
+ "override",
+ "reportFalsePositive"
+ ],
+ "description": "Indicates the action taken by the user on a message blocked by the DLP provider. Supported values are: none, override, reportFalsePositive."
+ },
+ "verdictDetails": {
+ "type": "string",
+ "enum": [
+ "none",
+ "allowFalsePositiveOverride",
+ "allowOverrideWithoutJustification",
+ "allowOverrideWithJustification"
+ ],
+ "description": "Indicates what actions the sender may take in response to the policy violation. Supported values are: none, allowFalsePositiveOverride, allowOverrideWithoutJustification, allowOverrideWithJustification."
+ }
+ }
+ },
+ "messageType": {
+ "type": "string",
+ "enum": [
+ "message",
+ "chatEvent",
+ "typing",
+ "unknownFutureValue",
+ "systemEventMessage"
+ ],
+ "description": "The type of chat message. The possible values are: message, chatEvent, typing, unknownFutureValue, systemEventMessage.",
+ "default": "message"
+ }
+ },
+ "required": [
+ "chatId",
+ "body"
+ ]
+ }
+ },
+ {
+ "name": "soft_delete_chat_message",
+ "description": "Delete a single chatMessage in a chat (Microsoft Graph API compliant). API Endpoint: POST /users/{userId}/chats/{chatsId}/messages/{chatMessageId}/softDelete.\n\n Microsoft Graph API Permissions (exact from documentation):\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | Chat.ReadWrite\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Don't supply a request body for this method\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - This API works differently in one or more national clouds\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response: 204 No Content on success\n\n Note: This implements the Microsoft Graph API endpoint /users/{userId}/chats/{chatsId}/messages/{chatMessageId}/softDelete\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to soft delete"
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "undo_soft_delete_chat_message",
+ "description": "Undo soft deletion of a single chatMessage in a chat (Microsoft Graph API compliant). API Endpoint: POST /users/{userId}/chats/{chatsId}/messages/{chatMessageId}/undoSoftDelete.\n\n Microsoft Graph API Permissions (exact from documentation):\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | Chat.ReadWrite\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Don't supply a request body for this method\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response: 204 No Content on success\n\n Note: This implements the Microsoft Graph API endpoint /users/{userId}/chats/{chatsId}/messages/{chatMessageId}/undoSoftDelete\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to restore"
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "update_chat_message",
+ "description": "Update a chat message (Microsoft Graph API compliant). API Endpoint: PATCH /chats/{chat_id}/messages/{message_id}.\n\n Microsoft Graph API Permissions (exact from documentation):\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | Chat.ReadWrite\n Delegated (personal Microsoft account) | Not supported\n Application | Chat.UpdatePolicyViolation.All, Chat.ReadWrite.All\n\n Important Constraints:\n - Delegated permissions: ALL properties can be updated EXCEPT policyViolation\n - Application permissions: ONLY policyViolation property can be updated (Chat.UpdatePolicyViolation.All) OR all properties can be updated (Chat.ReadWrite.All)\n - Only works for chats where members are Microsoft Teams users (if Skype user present, operation fails)\n - Only the user who sent the message can perform updates\n - This method doesn't support federation\n - When used with application permissions, this API is metered and supports model=A payment model\n\n Response Codes: Delegated permissions (204 No Content), Application permissions (200 OK for policyViolation updates)",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to update"
+ },
+ "body": {
+ "type": "object",
+ "description": "Updated message body content",
+ "properties": {
+ "content": {
+ "type": "string",
+ "description": "Updated content of the message"
+ },
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "Content type of the message",
+ "default": "text"
+ }
+ },
+ "required": [
+ "content"
+ ]
+ },
+ "subject": {
+ "type": "string",
+ "description": "Updated subject of the message"
+ },
+ "importance": {
+ "type": "string",
+ "enum": [
+ "normal",
+ "high",
+ "urgent"
+ ],
+ "description": "Updated importance level of the message"
+ },
+ "attachments": {
+ "type": "array",
+ "description": "Updated file attachments",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "contentType": {
+ "type": "string"
+ },
+ "contentUrl": {
+ "type": "string"
+ },
+ "content": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "thumbnailUrl": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "mentions": {
+ "type": "array",
+ "description": "Updated user mentions in the message",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "mentionText": {
+ "type": "string"
+ },
+ "mentioned": {
+ "type": "object",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "userIdentityType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "reactions": {
+ "type": "array",
+ "description": "Updated message reactions",
+ "items": {
+ "type": "object",
+ "properties": {
+ "reactionType": {
+ "type": "string"
+ },
+ "createdDateTime": {
+ "type": "string"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "userIdentityType": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "messageHistory": {
+ "type": "array",
+ "description": "Updated message edit history",
+ "items": {
+ "type": "object",
+ "properties": {
+ "modifiedDateTime": {
+ "type": "string"
+ },
+ "actions": {
+ "type": "string"
+ },
+ "reaction": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "policyViolation": {
+ "type": "object",
+ "description": "ONLY application permissions (Chat.UpdatePolicyViolation.All) can update this property. Defines the properties of a policy violation set by a data loss prevention (DLP) application.",
+ "properties": {
+ "dlpAction": {
+ "type": "string",
+ "enum": [
+ "none",
+ "notifySender",
+ "blockAccess",
+ "blockAccessExternal"
+ ],
+ "description": "The action taken by the DLP provider on the message. Supported values are: none, notifySender, blockAccess, blockAccessExternal."
+ },
+ "justificationText": {
+ "type": "string",
+ "description": "Justification text provided by the sender of the message when overriding a policy violation."
+ },
+ "policyTip": {
+ "type": "object",
+ "description": "Information to display to the message sender about why the message was flagged as a violation.",
+ "properties": {
+ "generalText": {
+ "type": "string"
+ },
+ "complianceUrl": {
+ "type": "string"
+ },
+ "matchedConditionDescriptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "userAction": {
+ "type": "string",
+ "enum": [
+ "none",
+ "override",
+ "reportFalsePositive"
+ ],
+ "description": "Indicates the action taken by the user on a message blocked by the DLP provider. Supported values are: none, override, reportFalsePositive."
+ },
+ "verdictDetails": {
+ "type": "string",
+ "enum": [
+ "none",
+ "allowFalsePositiveOverride",
+ "allowOverrideWithoutJustification",
+ "allowOverrideWithJustification"
+ ],
+ "description": "Indicates what actions the sender may take in response to the policy violation. Supported values are: none, allowFalsePositiveOverride, allowOverrideWithoutJustification, allowOverrideWithJustification."
+ }
+ }
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "set_chat_message_reaction",
+ "description": "Set a reaction to a chat message (Microsoft Graph API compliant).\n\n API Endpoint: POST /chats/{chatId}/messages/{messageId}/setReaction\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | Chat.ReadWrite, ChatMessage.Send\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n - Request body must supply the reactionType as unicode\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier",
+ "minLength": 1
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to react to",
+ "minLength": 1
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "The reaction type as unicode (e.g., '\ud83d\udc98', '\ud83d\udc4d', '\u2764\ufe0f', '\ud83d\ude02', '\ud83d\ude2e', '\ud83d\ude22', '\ud83d\ude21')",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId",
+ "reactionType"
+ ]
+ }
+ },
+ {
+ "name": "unset_chat_message_reaction",
+ "description": "Unset a reaction from a chat message (Microsoft Graph API compliant).\n\n API Endpoint: POST /chats/{chatId}/messages/{messageId}/unsetReaction\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | Chat.ReadWrite, ChatMessage.Send\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n - Request body must supply the reactionType as unicode\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier",
+ "minLength": 1
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to remove reaction from",
+ "minLength": 1
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "The reaction type as unicode to remove (e.g., '\ud83d\udc98', '\ud83d\udc4d', '\u2764\ufe0f', '\ud83d\ude02', '\ud83d\ude2e', '\ud83d\ude22', '\ud83d\ude21')",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId",
+ "reactionType"
+ ]
+ }
+ },
+ {
+ "name": "pin_chat_message",
+ "description": "Pin a message in a chat (Microsoft Graph API compliant).\n\n Pin a chat message in the specified chat. This API cannot create a new chat; you must use the list chats method to retrieve the ID of an existing chat before you can pin a chat message.\n\n Required Permissions:\n - Delegated (work or school account): Chat.ReadWrite (least privileged)\n - Delegated (personal Microsoft account): Not supported\n - Application: Chat.ReadWrite.All (least privileged)\n\n API Endpoint: POST /chats/{chat_id}/pinnedMessages",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "chatId": {
+ "type": "string",
+ "description": "Unique chat identifier",
+ "minLength": 1
+ },
+ "messageId": {
+ "type": "string",
+ "description": "The unique identifier of the message to pin",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "chatId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "create_channel",
+ "description": "Create a new channel in a team. API Endpoint: POST /teams/{team-id}/channels",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier where the channel will be created"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Channel display name",
+ "maxLength": 50,
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "description": "Channel description (optional)",
+ "maxLength": 1024
+ },
+ "membershipType": {
+ "type": "string",
+ "enum": [
+ "standard",
+ "private",
+ "shared"
+ ],
+ "description": "Channel membership type",
+ "default": "standard"
+ },
+ "members": {
+ "type": "array",
+ "description": "Initial channel members (required for private/shared channels)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "user_odata_bind": {
+ "type": "string",
+ "description": "OData bind URL for user reference (e.g., https://graph.microsoft.com/v1.0/users/{user-id})"
+ },
+ "roles": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "member",
+ "guest"
+ ]
+ },
+ "description": "Roles assigned to the user. Per Microsoft Graph API: 'owner' for owner privileges, 'guest' for in-tenant guest users, empty array for basic members. Out-of-tenant external members are assigned 'owner' role.",
+ "default": [
+ "member"
+ ]
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user"
+ },
+ "email": {
+ "type": "string",
+ "description": "Email address of the user"
+ }
+ },
+ "required": [
+ "user_odata_bind"
+ ]
+ }
+ },
+ "isFavoriteByDefault": {
+ "type": "boolean",
+ "description": "Whether channel is favorite by default",
+ "default": false
+ },
+ "_microsoft_graph_channelCreationMode": {
+ "type": "string",
+ "enum": [
+ "migration"
+ ],
+ "description": "Special creation mode for data migration. When specified, createdDateTime can be provided."
+ }
+ },
+ "required": [
+ "teamId",
+ "displayName"
+ ]
+ }
+ },
+ {
+ "name": "update_channel",
+ "description": "Update a channel's properties. API Endpoint: PATCH /teams/{team-id}/channels/{channel-id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Updated channel display name",
+ "maxLength": 50,
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "description": "Updated channel description",
+ "maxLength": 1024
+ },
+ "isFavoriteByDefault": {
+ "type": "boolean",
+ "description": "Updated favorite by default setting"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ],
+ "minProperties": 3
+ }
+ },
+ {
+ "name": "list_channels",
+ "description": "Retrieve the list of channels in a team (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/channels\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | Channel.ReadBasic.All | ChannelSettings.Read.All, ChannelSettings.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | ChannelSettings.Read.Group | Channel.ReadBasic.All, ChannelSettings.Read.All, ChannelSettings.ReadWrite.All, ChannelSettings.ReadWrite.Group, Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n\n Important Access Control:\n - Only team members can access channels (enforced by team membership verification)\n - Guest users can't see private or shared channels they aren't members of\n - Unicode characters in parameters are sanitized to prevent encoding errors\n\n Query Parameters Support:\n - _filter: Supports 'membershipType eq private', 'membershipType eq shared', 'membershipType eq standard'\n - _select: Exclude email property for better performance (recommended by Microsoft Graph API)\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier (must be a team where the user is a member)"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression. Examples: 'membershipType eq \\'private\\'', 'membershipType eq \\'shared\\'', 'membershipType eq \\'standard\\''",
+ "examples": [
+ "membershipType eq 'private'",
+ "membershipType eq 'shared'",
+ "membershipType eq 'standard'"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return for performance optimization. Recommended to exclude 'email' property per Microsoft Graph API guidance.",
+ "examples": [
+ "displayName,description,membershipType",
+ "id,displayName,isArchived"
+ ]
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "list_all_channels",
+ "description": "Get the list of channels either in this team or shared with this team (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/allChannels\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | Channel.ReadBasic.All | ChannelSettings.Read.All, ChannelSettings.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | Channel.ReadBasic.All | ChannelSettings.Read.All, ChannelSettings.ReadWrite.All\n\n Permission-Based Field Restrictions:\n - Channel.ReadBasic.All: Returns ONLY displayName and description fields (per Microsoft Graph API spec: \"Read the names and descriptions of all channels\")\n - ChannelSettings.Read.All or higher: Returns all channel properties including id, createdDateTime, membershipType, tenantId, isArchived, etc.\n - Response always includes @odata.id property for Microsoft Graph API compliance\n\n Important Features:\n - This API supports admin permissions. Microsoft Teams service admins can access teams that they are not a member of\n - Use _select to exclude the email and moderationSettings properties for better performance\n - Supports _filter for membershipType (e.g., 'membershipType eq shared', 'membershipType eq private', 'membershipType eq standard')\n - Response includes @odata.id property which can be used to access the channel\n - Lists all channels in the team and shared channels from other teams\n\n Sample Requests:\n - All channels: GET /teams/{team-id}/allChannels\n - Only shared channels: GET /teams/{team-id}/allChannels?_filter=membershipType eq 'shared'\n - Performance optimized: GET /teams/{team-id}/allChannels?_select=displayName,membershipType\n - Basic permission (Channel.ReadBasic.All): Returns only displayName and description automatically\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier (use team_techcorp_001 or team_globalex_002 for sample data)"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression for membershipType filtering",
+ "examples": [
+ "membershipType eq 'shared'",
+ "membershipType eq 'private'",
+ "membershipType eq 'standard'"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return for performance optimization. Recommended to exclude email and moderationSettings properties.",
+ "examples": [
+ "displayName,membershipType",
+ "id,displayName,isArchived",
+ "displayName,description,membershipType"
+ ]
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "get_primary_channel",
+ "description": "Get the primary channel (General channel) for a team (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/primaryChannel\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | Channel.ReadBasic.All | ChannelSettings.Read.All, ChannelSettings.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | ChannelSettings.Read.Group | Channel.ReadBasic.All, ChannelSettings.Read.All, ChannelSettings.ReadWrite.All, ChannelSettings.ReadWrite.Group\n\n Important Notes:\n - This API supports admin permissions. Microsoft Teams service admins can access teams that they are not a member of\n - The ChannelSettings.Read.Group and ChannelSettings.ReadWrite.Group permissions use resource-specific consent\n - Returns the default \"General\" channel for a team\n - Only team members can access the primary channel (unless admin permissions)\n - Use _select for better performance\n\n Query Parameters Support:\n - _filter: OData filter expression (e.g., 'membershipType eq \\'standard\\'')\n - _select: OData select expression for better performance\n - _expand: OData expand expression\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier (must be a team where the user is a member or user has admin permissions)"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression. Examples: 'membershipType eq \\'standard\\'', 'membershipType eq \\'private\\'', 'membershipType eq \\'shared\\''",
+ "examples": [
+ "membershipType eq 'standard'",
+ "membershipType eq 'private'",
+ "membershipType eq 'shared'"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return for better performance. Use this to optimize query performance.",
+ "examples": [
+ "displayName,description,membershipType",
+ "id,displayName,createdDateTime",
+ "displayName,webUrl"
+ ]
+ },
+ "_expand": {
+ "type": "string",
+ "description": "OData expand expression to include related entities",
+ "examples": [
+ "members",
+ "tabs"
+ ]
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "add_channel_member",
+ "description": "Add a member to a channel (Microsoft Graph API compliant).\n\n API Endpoint: POST /teams/{team-id}/channels/{channel-id}/members\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | ChannelMember.ReadWrite.All | Not available\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | ChannelMember.ReadWrite.Group | ChannelMember.ReadWrite.All\n\n Important Notes:\n - This operation is allowed only for channels with a membershipType value of private or shared\n - The app must be preinstalled in the team\n - Returns 404 Not Found when you attempt to add a disabled/blocked user\n - Status code 201 Created on success\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "_odata_type": {
+ "type": "string",
+ "description": "OData type indicator",
+ "default": "#microsoft.graph.aadUserConversationMember"
+ },
+ "user_odata_bind": {
+ "type": "string",
+ "description": "OData bind URL for the user. Format: 'https://graph.microsoft.com/v1.0/users('{user-id}')' or 'https://graph.microsoft.com/v1.0/users('{user-principal-name}')'",
+ "examples": [
+ "https://graph.microsoft.com/v1.0/users('8b081ef6-4792-4def-b2c9-c363a1bf41d5')",
+ "https://graph.microsoft.com/v1.0/users('jacob@contoso.com')"
+ ]
+ },
+ "roles": {
+ "type": "array",
+ "description": "The role for the user. Must be 'owner' or empty.",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner"
+ ]
+ },
+ "default": []
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "user_odata_bind"
+ ]
+ }
+ },
+ {
+ "name": "archive_channel",
+ "description": "Archive a channel (Microsoft Graph API compliant).\n\n API Endpoint: POST /teams/{team-id}/channels/{channel-id}/archive\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | ChannelSettings.ReadWrite.All | Not available\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | ChannelSettings.ReadWrite.All | Not available\n\n Important Notes:\n - Archives a channel in a team\n - Archived channels are read-only (users cannot post new messages)\n - Existing messages can still be read\n - Cannot archive the General channel\n - Status code 204 No Content on success\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier to archive"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ]
+ }
+ },
+ {
+ "name": "list_channel_messages",
+ "description": "List messages in a channel. API Endpoint: GET /teams/{team-id}/channels/{channel-id}/messages",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "_top": {
+ "type": "integer",
+ "description": "Number of messages to return",
+ "minimum": 1,
+ "maximum": 50,
+ "default": 20
+ },
+ "_expand": {
+ "type": "string",
+ "description": "OData expand parameter to include related entities (e.g., 'replies' to include message replies)",
+ "examples": [
+ "replies",
+ "replies(_top=5)",
+ "hostedContents"
+ ]
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ]
+ }
+ },
+ {
+ "name": "send_channel_message",
+ "description": "Send a new chatMessage in the specified channel (Microsoft Graph API compliant).\n\n API Endpoint:\n - POST /teams/{team-id}/channels/{channel-id}/messages\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | ChannelMessage.Send | Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | Teamwork.Migrate.All | Not available\n\n Important Constraints:\n - The Group.ReadWrite.All permission is supported only for backward compatibility\n - Application permissions are only supported for migration\n - Don't recommend using this API for data migration (throughput limited to 10 messages every 10 seconds)\n - It is a violation of the terms of use to use Microsoft Teams as a log file - only send messages that people will read\n - Only the body property is mandatory; other properties are optional\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response: 201 Created with new chatMessage object",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "body": {
+ "type": "object",
+ "description": "The message body content (MANDATORY property - only required field per Microsoft Graph API)",
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "The content type of the message body",
+ "default": "text"
+ },
+ "content": {
+ "type": "string",
+ "description": "The actual message content"
+ }
+ },
+ "required": [
+ "content"
+ ]
+ },
+ "subject": {
+ "type": "string",
+ "description": "Optional subject line for the message",
+ "maxLength": 255
+ },
+ "attachments": {
+ "type": "array",
+ "description": "Optional message attachments",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Attachment identifier"
+ },
+ "contentType": {
+ "type": "string",
+ "description": "MIME type of the attachment"
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL to the attachment content"
+ },
+ "content": {
+ "type": "string",
+ "description": "Base64-encoded attachment content"
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the attachment"
+ },
+ "thumbnailUrl": {
+ "type": "string",
+ "description": "URL to attachment thumbnail"
+ }
+ }
+ }
+ },
+ "mentions": {
+ "type": "array",
+ "description": "Users mentioned in the message",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "description": "Index of the mention in the message"
+ },
+ "mentionText": {
+ "type": "string",
+ "description": "The mention text (e.g., user's name)"
+ },
+ "mentioned": {
+ "type": "object",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "User display name"
+ },
+ "userIdentityType": {
+ "type": "string",
+ "enum": [
+ "aadUser"
+ ],
+ "description": "Type of user identity",
+ "default": "aadUser"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ "required": [
+ "user"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "mentionText",
+ "mentioned"
+ ]
+ }
+ },
+ "importance": {
+ "type": "string",
+ "enum": [
+ "normal",
+ "high",
+ "urgent"
+ ],
+ "description": "Message importance level",
+ "default": "normal"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "body"
+ ]
+ }
+ },
+ {
+ "name": "soft_delete_channel_message",
+ "description": "Delete a single chatMessage or reply in a channel (Microsoft Graph API compliant).\n\n API Endpoints:\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/softDelete\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies/{reply-id}/softDelete\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | ChannelMessage.ReadWrite\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Don't supply a request body for this method\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to soft delete"
+ },
+ "replyId": {
+ "type": "string",
+ "description": "Optional reply identifier (for soft deleting a specific reply to a message)"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "undo_soft_delete_channel_message",
+ "description": "Undo soft deletion of a single chatMessage or reply in a channel (Microsoft Graph API compliant).\n\n API Endpoints:\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/undoSoftDelete\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies/{reply-id}/undoSoftDelete\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | ChannelMessage.ReadWrite\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Don't supply a request body for this method\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to restore"
+ },
+ "replyId": {
+ "type": "string",
+ "description": "Optional reply identifier (for restoring a specific reply to a message)"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "update_channel_message",
+ "description": "Update a chatMessage in a channel (Microsoft Graph API compliant).\n\n ONLY 3 FIELDS ARE REQUIRED:\n 1. teamId (REQUIRED)\n 2. channelId (REQUIRED)\n 3. messageId (REQUIRED)\n\n ALL OTHER FIELDS ARE OPTIONAL - Only provide fields you want to update!\n DO NOT send fields with empty values!\n\n Example: To update only message content, send ONLY teamId, channelId, messageId, and body with non-empty content.\n\n API Endpoints:\n - PATCH /teams/{team-id}/channels/{channel-id}/messages/{message-id}\n - PATCH /teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies/{reply-id}\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permissions for channel:\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | ChannelMessage.ReadWrite, Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported\n Application | ChannelMessage.UpdatePolicyViolation.All, Group.ReadWrite.All\n\n Important Constraints:\n - The Group.ReadWrite.All permission is supported only for backward compatibility (update solutions to use alternative permissions)\n - For delegated permissions: ALL properties of a chatMessage can be updated EXCEPT the policyViolation property\n - For application permissions: ONLY the policyViolation property can be updated\n - The update only works for chats where members are Microsoft Teams users. If one participant is using Skype, the operation fails\n - This method doesn't support federation. Only the user in the tenant who sent the message can perform data loss prevention (DLP) updates on the specified chat message\n - When used with application permissions, this API is metered. It supports the model=A payment model. For details, see Payment models. If you don't specify a payment model in your query, the default evaluation mode will be used\n - Available in national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Response:\n - For delegated permissions: 204 No Content\n - For application permissions: 200 OK",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier to update"
+ },
+ "replyId": {
+ "type": "string",
+ "description": "Optional reply identifier to update a specific reply to a message"
+ },
+ "model": {
+ "type": "string",
+ "description": "Payment model for licensing (evaluation mode used if not specified). Only supports value 'A'",
+ "enum": [
+ "A"
+ ]
+ },
+ "messageType": {
+ "type": "string",
+ "enum": [
+ "message"
+ ],
+ "description": "The type of chat message",
+ "default": "message"
+ },
+ "subject": {
+ "type": "string",
+ "description": "The subject line of the chat message (can be null)"
+ },
+ "summary": {
+ "type": "string",
+ "description": "Summary text of the chat message that could be used for push notifications and summary views (can be null)"
+ },
+ "importance": {
+ "type": "string",
+ "enum": [
+ "normal",
+ "high",
+ "urgent"
+ ],
+ "description": "The importance of the chat message",
+ "default": "normal"
+ },
+ "locale": {
+ "type": "string",
+ "description": "Locale of the chat message set by the client (e.g., 'en-us')"
+ },
+ "from": {
+ "type": "object",
+ "description": "Details of the sender of the chat message (read-only during updates)",
+ "properties": {
+ "application": {
+ "type": "object",
+ "description": "Application identity set (if sender is an application)"
+ },
+ "device": {
+ "type": "object",
+ "description": "Device identity set (if sender is a device)"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user"
+ },
+ "userIdentityType": {
+ "type": "string",
+ "enum": [
+ "aadUser"
+ ],
+ "description": "Type of user identity",
+ "default": "aadUser"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ },
+ "conversation": {
+ "type": "object",
+ "description": "Conversation identity set (usually null)"
+ }
+ }
+ },
+ "body": {
+ "type": "object",
+ "description": "Updated message body content (OPTIONAL - only provide if updating message body. If provided, content cannot be empty)",
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "The content type of the message body",
+ "default": "text"
+ },
+ "content": {
+ "type": "string",
+ "description": "The updated message content (REQUIRED if body is provided, CANNOT BE EMPTY)",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "content"
+ ]
+ },
+ "attachments": {
+ "type": "array",
+ "description": "References to attached objects like files, tabs, meetings etc.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Attachment identifier"
+ },
+ "contentType": {
+ "type": "string",
+ "description": "The media type of the content attachment"
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL for the content of the attachment"
+ },
+ "content": {
+ "type": "string",
+ "description": "The content of the attachment"
+ },
+ "name": {
+ "type": "string",
+ "description": "Name of the attachment"
+ },
+ "thumbnailUrl": {
+ "type": "string",
+ "description": "URL to a thumbnail image for the attachment"
+ }
+ }
+ }
+ },
+ "mentions": {
+ "type": "array",
+ "description": "List of entities mentioned in the chat message",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "description": "Index of an entity being mentioned in the specified chatMessage"
+ },
+ "mentionText": {
+ "type": "string",
+ "description": "String used to represent the mention (e.g. a user's display name, a team name)"
+ },
+ "mentioned": {
+ "type": "object",
+ "properties": {
+ "application": {
+ "type": "object",
+ "description": "Application identity set (if mentioning an application)"
+ },
+ "device": {
+ "type": "object",
+ "description": "Device identity set (if mentioning a device)"
+ },
+ "conversation": {
+ "type": "object",
+ "description": "Conversation identity set (if mentioning a conversation)"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user"
+ },
+ "userIdentityType": {
+ "type": "string",
+ "enum": [
+ "aadUser"
+ ],
+ "description": "Type of user identity",
+ "default": "aadUser"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ }
+ }
+ },
+ "required": [
+ "id",
+ "mentionText",
+ "mentioned"
+ ]
+ }
+ },
+ "reactions": {
+ "type": "array",
+ "description": "Reactions for this chat message (for example, Like)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "reactionType": {
+ "type": "string",
+ "description": "Supported values are like, angry, sad, laugh, heart, surprised"
+ },
+ "createdDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "The Timestamp type represents date and time information using ISO 8601 format"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "application": {
+ "type": "object",
+ "description": "Application identity set"
+ },
+ "device": {
+ "type": "object",
+ "description": "Device identity set"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Display name of the user"
+ },
+ "userIdentityType": {
+ "type": "string",
+ "enum": [
+ "aadUser"
+ ],
+ "description": "Type of user identity",
+ "default": "aadUser"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "messageHistory": {
+ "type": "array",
+ "description": "List of activity history of a message item",
+ "items": {
+ "type": "object",
+ "properties": {
+ "modifiedDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "The date and time when the message was modified"
+ },
+ "actions": {
+ "type": "string",
+ "description": "The action performed on the message"
+ },
+ "reaction": {
+ "type": "object",
+ "description": "The reaction details if the action was a reaction"
+ }
+ }
+ }
+ },
+ "policyViolation": {
+ "type": "object",
+ "description": "Defines the properties of a policy violation set by a data loss prevention (DLP) application. FOR APPLICATION PERMISSIONS: This is the ONLY property that can be updated.",
+ "properties": {
+ "policyTip": {
+ "type": "object",
+ "properties": {
+ "generalText": {
+ "type": "string",
+ "description": "Explanatory text shown to the sender of the message"
+ },
+ "complianceUrl": {
+ "type": "string",
+ "description": "The URL a sender can visit to read about the data loss prevention policies for the organization"
+ },
+ "matchedConditionDescriptions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "The list of improper data in the message that was detected by the data loss prevention app"
+ }
+ }
+ },
+ "verdictDetails": {
+ "type": "string",
+ "description": "Indicates what actions the sender may take in response to the policy violation"
+ },
+ "dlpAction": {
+ "type": "string",
+ "description": "Indicates the action taken by the DLP provider on the message"
+ }
+ }
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "messageId"
+ ]
+ }
+ },
+ {
+ "name": "set_channel_message_reaction",
+ "description": "Set a reaction to a channel message or reply (Microsoft Graph API compliant).\n\n API Endpoints:\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/setReaction\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies/{reply-id}/setReaction\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | ChannelMessage.Send\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n - Request body must supply the reactionType as unicode\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier"
+ },
+ "replyId": {
+ "type": "string",
+ "description": "Optional reply identifier (for setting reaction on a reply)"
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "Reaction type as unicode (e.g., '\ud83d\udc98', '\ud83d\udc4d', '\u2764\ufe0f', '\ud83d\ude02', '\ud83d\ude2e', '\ud83d\ude22', '\ud83d\ude21')"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "messageId",
+ "reactionType"
+ ]
+ }
+ },
+ {
+ "name": "unset_channel_message_reaction",
+ "description": "Unset a reaction from a channel message or reply (Microsoft Graph API compliant).\n\n API Endpoints:\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/unsetReaction\n - POST /teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies/{reply-id}/unsetReaction\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Permissions (from least to most privileged)\n Delegated (work or school account) | ChannelMessage.Send\n Delegated (personal Microsoft account) | Not supported\n Application | Not supported\n\n Important Constraints:\n - Only delegated permissions are supported (application permissions NOT supported)\n - Personal Microsoft accounts are not supported\n - Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n - Request body must supply the reactionType as unicode\n\n Response: 204 No Content on success",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "messageId": {
+ "type": "string",
+ "description": "Unique message identifier"
+ },
+ "replyId": {
+ "type": "string",
+ "description": "Optional reply identifier (for unsetting reaction from a reply)"
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "Reaction type as unicode (e.g., '\ud83d\udc98', '\ud83d\udc4d', '\u2764\ufe0f', '\ud83d\ude02', '\ud83d\ude2e', '\ud83d\ude22', '\ud83d\ude21')"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "messageId",
+ "reactionType"
+ ]
+ }
+ },
+ {
+ "name": "get_files_folder",
+ "description": "Get the metadata for the location where the files of a channel are stored (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/channels/{channel-id}/filesFolder\n\n Microsoft Graph API Permissions:\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | Files.Read.All | Files.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | Files.Read.All | Files.ReadWrite.All, Group.Read.All, Group.ReadWrite.All\n\n Important Notes:\n - This API supports admin permissions\n - Returns metadata about the default file storage location (OneDrive folder) for the channel\n - The folder is automatically created when first file is uploaded to the channel\n - Special characters in the channel name may cause issues with this API\n\n Returns:\n - driveItem object representing the folder where channel files are stored",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ]
+ }
+ },
+ {
+ "name": "list_tabs_in_channel",
+ "description": "Retrieve the list of tabs in the specified channel within a team (Microsoft Graph API compliant).\n\n API Endpoint: GET /teams/{team-id}/channels/{channel-id}/tabs\n\n Microsoft Graph API Permissions:\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | TeamsTab.Read.All | Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam, TeamsTab.ReadWriteSelfForTeam\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | TeamsTab.Read.Group | Directory.Read.All, Directory.ReadWrite.All, Group.Read.All, Group.ReadWrite.All, TeamsTab.Read.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWrite.Group, TeamsTab.ReadWriteForTeam.All, TeamsTab.ReadWriteSelfForTeam.All\n\n Important Notes:\n - This API supports admin permissions\n - The TeamsTab.Read.Group and TeamsTab.ReadWrite.Group permissions use resource-specific consent\n - The Group.Read.All, Group.ReadWrite.All, Directory.Read.All, and Directory.ReadWrite.All permissions are supported only for backward compatibility\n - This method supports _filter, _select, and _expand OData query parameters\n - Note: The Files tab is native to a channel or chat and is not returned by this API\n\n Query Parameters Support:\n - _filter: Filter by teamsApp/id (e.g., 'teamsApp/id eq \\'appId\\'')\n - _select: Select specific properties\n - _expand: Expand related entities (e.g., 'teamsApp' to include app details)\n\n Returns:\n - Collection of teamsTab objects",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression (e.g., 'teamsApp/id eq \\'com.microsoft.teamspace.tab.wiki\\'')",
+ "examples": [
+ "teamsApp/id eq 'com.microsoft.teamspace.tab.wiki'",
+ "displayName eq 'Marketing'"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return",
+ "examples": [
+ "displayName,webUrl",
+ "id,displayName,sortOrderIndex"
+ ]
+ },
+ "_expand": {
+ "type": "string",
+ "description": "OData expand expression (e.g., 'teamsApp' to include app details)",
+ "examples": [
+ "teamsApp",
+ "teamsApp(_select=displayName)"
+ ]
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ]
+ }
+ },
+ {
+ "name": "add_tabs_to_channels",
+ "description": "Add (pin) a tab to the specified channel within a team (Microsoft Graph API compliant).\n\n API Endpoint: POST /teams/{team-id}/channels/{channel-id}/tabs\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | TeamsTab.Create | Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam, TeamsTab.ReadWriteSelfForTeam\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | TeamsTab.Create.Group | Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.Create, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam.All, TeamsTab.ReadWriteSelfForTeam.All\n\n Important Notes:\n - This API supports admin permissions. Microsoft Teams service admins can access teams that they aren't a member of\n - The app must be preinstalled in the team and have the configurableTabs property defined in the app manifest\n - The TeamsTab.Create.Group permission uses resource-specific consent\n - The Group.ReadWrite.All and Directory.ReadWrite.All permissions are supported only for backward compatibility\n - If the app manifest contains a static tab matching the current scope (team), the static tab is pinned by default\n - For static tabs: If displayName and configuration are specified in the request body, the API returns 400 Bad Request\n - Returns 201 Created with the new tab object on success\n\n Available in all national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Request Body Example:\n {\n \"displayName\": \"My Contoso Tab\",\n \"teamsApp_odata_bind\": \"https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/06805b9e-77e3-4b93-ac81-525eb87513b8\",\n \"configuration\": {\n \"entityId\": \"2DCA2E6C7A10415CAF6B8AB6661B3154\",\n \"contentUrl\": \"https://www.contoso.com/Orders/2DCA2E6C7A10415CAF6B8AB6661B3154/tabView\",\n \"websiteUrl\": \"https://www.contoso.com/Orders/2DCA2E6C7A10415CAF6B8AB6661B3154\",\n \"removeUrl\": \"https://www.contoso.com/Orders/2DCA2E6C7A10415CAF6B8AB6661B3154/uninstallTab\"\n }\n }",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier where the tab will be added"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier where the tab will be pinned"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Name of the tab as it will appear to users in Microsoft Teams"
+ },
+ "teamsApp_odata_bind": {
+ "type": "string",
+ "description": "OData bind URL for the Teams app to pin as a tab. Format: 'https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/{app-id}'. The app must be preinstalled in the team.",
+ "examples": [
+ "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/06805b9e-77e3-4b93-ac81-525eb87513b8"
+ ]
+ },
+ "configuration": {
+ "type": "object",
+ "description": "Container for custom settings applied to a tab (required for configurable tabs)",
+ "properties": {
+ "entityId": {
+ "type": "string",
+ "description": "Identifier for the entity hosted by the tab provider"
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL used for rendering tab contents in Teams. Required for configurable tabs."
+ },
+ "websiteUrl": {
+ "type": "string",
+ "description": "URL for showing tab contents outside of Teams"
+ },
+ "removeUrl": {
+ "type": "string",
+ "description": "URL called by Teams when the tab is removed"
+ }
+ }
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "displayName",
+ "teamsApp_odata_bind"
+ ]
+ }
+ },
+ {
+ "name": "provision_channel_email",
+ "description": "Provision an email address for a channel (Microsoft Graph API compliant).\n\n API Endpoint: POST /teams/{team-id}/channels/{channel-id}/provisionEmail\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | ChannelSettings.ReadWrite.All | Not available\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | Not supported | Not supported\n\n Important Notes:\n - Microsoft Teams doesn't automatically provision an email address for a channel by default\n - To have Teams provision an email address, you can call provisionEmail, or through the\n Teams user interface, select Get email address, which triggers Teams to generate an\n email address if it has not already provisioned one\n - To remove the email address of a channel, use the removeEmail method\n - ONLY delegated permissions are supported (application permissions NOT supported)\n - Returns 200 OK with provisionChannelEmailResult containing the email address\n - If email already exists, returns existing email (idempotent behavior)\n\n Request Body: None (empty)\n Response: 200 OK with provisionChannelEmailResult object\n\n Example Response:\n {\n \"@odata_type\": \"#microsoft.graph.provisionChannelEmailResult\",\n \"email\": \"contoso.com@amer.teams.ms\"\n }\n\n Available in national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet\n\n Reference:\n https://learn.microsoft.com/en-us/graph/api/channel-provisionemail?view=graph-rest-1.0&tabs=http",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier for which to provision email"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId"
+ ]
+ }
+ },
+ {
+ "name": "update_channel_tab",
+ "description": "Update the properties of a tab in a channel (Microsoft Graph API compliant).\n\n API Endpoint: PATCH /teams/{team-id}/channels/{channel-id}/tabs/{tab-id}\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | TeamsTab.ReadWriteSelfForTeam | Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | TeamsTab.ReadWrite.Group | Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam.All, TeamsTab.ReadWriteSelfForTeam.All\n\n Important Notes:\n - The TeamsTab.ReadWrite.Group permission uses resource-specific consent\n - The Directory and Group permissions are supported only for backward compatibility\n - Only displayName and configuration properties can be updated\n - Attempting to update read-only fields (id, webUrl, sortOrderIndex, messageId, teamsAppId, teamsApp) returns 400 Bad Request\n\n Updatable Properties ONLY:\n - displayName (string, 1-128 characters)\n - configuration (object)\n\n Read-Only Properties (cannot update):\n - id, webUrl, sortOrderIndex, messageId, teamsAppId, teamsApp\n\n Response: 200 OK with updated tab object\n\n Available in national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "tabId": {
+ "type": "string",
+ "description": "Unique tab identifier to update"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Updated tab display name (1-128 characters)",
+ "minLength": 1,
+ "maxLength": 128
+ },
+ "configuration": {
+ "type": "object",
+ "description": "Updated tab configuration settings",
+ "properties": {
+ "entityId": {
+ "type": "string",
+ "description": "Identifier for the entity hosted by the tab provider"
+ },
+ "contentUrl": {
+ "type": "string",
+ "description": "URL used for rendering tab contents in Teams"
+ },
+ "websiteUrl": {
+ "type": "string",
+ "description": "URL for showing tab contents outside of Teams"
+ },
+ "removeUrl": {
+ "type": "string",
+ "description": "URL called by Teams when the tab is removed"
+ }
+ }
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "tabId"
+ ]
+ }
+ },
+ {
+ "name": "delete_channel_tab",
+ "description": "Remove (unpin) a tab from a channel (Microsoft Graph API compliant).\n\n API Endpoint: DELETE /teams/{team-id}/channels/{channel-id}/tabs/{tab-id}\n\n Microsoft Graph API Permissions (exact from documentation):\n\n Permission type | Least privileged permissions | Higher privileged permissions\n Delegated (work or school account) | TeamsTab.ReadWriteSelfForTeam | Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam\n Delegated (personal Microsoft account) | Not supported | Not supported\n Application | TeamsTab.Delete.Group | TeamsTab.ReadWrite.Group, Directory.ReadWrite.All, Group.ReadWrite.All, TeamsTab.ReadWrite.All, TeamsTab.ReadWriteForTeam.All, TeamsTab.ReadWriteSelfForTeam.All\n\n Important Notes:\n - The TeamsTab.Delete.Group permission uses resource-specific consent\n - The Directory and Group permissions are supported only for backward compatibility\n - Removes the tab instance, but doesn't uninstall the Teams app\n - Cannot delete certain built-in/system tabs\n - Permanent operation - cannot be undone\n\n Request Body: None\n Response: 204 No Content (empty)\n\n Available in national cloud deployments: Global service , US Government L4 , US Government L5 (DOD) , China operated by 21Vianet ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "channelId": {
+ "type": "string",
+ "description": "Unique channel identifier"
+ },
+ "tabId": {
+ "type": "string",
+ "description": "Unique tab identifier to delete"
+ }
+ },
+ "required": [
+ "teamId",
+ "channelId",
+ "tabId"
+ ]
+ }
+ },
+ {
+ "name": "create_team",
+ "description": "Create a new team following MS Graph API v1.0. Two creation methods: 1) Create team with new group (requires template_odata_bind and displayName), 2) Create team from existing group (requires template_odata_bind and group_odata_bind). For Application permissions, members collection is REQUIRED. API Endpoint: POST /teams",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "template_odata_bind": {
+ "type": "string",
+ "description": "REQUIRED. Template reference (e.g., 'https://graph.microsoft.com/v1.0/teamsTemplates('standard')' or 'https://graph.microsoft.com/v1.0/teamsTemplates('educationClass')')"
+ },
+ "group_odata_bind": {
+ "type": "string",
+ "description": "OPTIONAL. Group reference for creating team from existing group (e.g., 'https://graph.microsoft.com/v1.0/groups('group-id')'). If provided, displayName becomes optional."
+ },
+ "members": {
+ "type": "array",
+ "description": "REQUIRED for Application permissions, OPTIONAL for Delegated permissions. Members to add to the team. At least one member with 'owner' role is required for Application permissions.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "_odata_type": {
+ "type": "string",
+ "description": "OData type identifier",
+ "default": "#microsoft.graph.aadUserConversationMember"
+ },
+ "roles": {
+ "type": "array",
+ "description": "Member roles (owner, member, guest). Must include at least one 'owner' for Application permissions.",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "member",
+ "guest"
+ ]
+ },
+ "default": [
+ "member"
+ ]
+ },
+ "user_odata_bind": {
+ "type": "string",
+ "description": "REQUIRED. User reference (e.g., 'https://graph.microsoft.com/v1.0/users('user-id')')"
+ },
+ "visibleHistoryStartDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "OPTIONAL. Timestamp denoting how far back conversation history is shared"
+ }
+ },
+ "required": [
+ "user_odata_bind"
+ ]
+ }
+ },
+ "displayName": {
+ "type": "string",
+ "description": "REQUIRED when creating new group (no group_odata_bind). Team display name.",
+ "maxLength": 255,
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "description": "Team description (optional)",
+ "maxLength": 1024
+ },
+ "classification": {
+ "type": "string",
+ "description": "OPTIONAL. An optional label. Typically describes the data or business sensitivity of the team. Must match one of a preconfigured set in the tenant's directory."
+ },
+ "tenantId": {
+ "type": "string",
+ "description": "OPTIONAL. Tenant identifier. If not provided, will be auto-fetched from the organization. If provided, will be validated against the orgs table to ensure it exists and belongs to the user's organization.",
+ "maxLength": 128
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "private",
+ "public",
+ "hiddenMembership"
+ ],
+ "description": "Team visibility",
+ "default": "private"
+ },
+ "specialization": {
+ "type": "string",
+ "enum": [
+ "none",
+ "educationStandard",
+ "educationClass",
+ "educationProfessionalLearningCommunity",
+ "educationSpecialInterest",
+ "healthcareStandard",
+ "healthcareCareCoordination",
+ "unknownFutureValue"
+ ],
+ "description": "Team specialization",
+ "default": "none"
+ },
+ "createdDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "OPTIONAL. Timestamp at which the team was created. Used only in migration mode (ISO 8601 format, e.g., '2020-03-14T11:22:17.067Z')"
+ },
+ "_microsoft_graph_teamCreationMode": {
+ "type": "string",
+ "enum": [
+ "migration"
+ ],
+ "description": "OPTIONAL. Indicates that the team is in migration state and is currently being used for migration purposes. Set to 'migration' to create a team in migration mode. Note: In the future, Microsoft may require you or your customers to pay additional fees based on the amount of data imported."
+ },
+ "classSettings": {
+ "type": "object",
+ "description": "OPTIONAL. Configure settings of a class. Available only when the team represents a class (specialization is educationClass).",
+ "properties": {
+ "notifyGuardiansAboutAssignments": {
+ "type": "boolean",
+ "description": "If set to true, enables sending of weekly assignments digest emails to parents/guardians"
+ }
+ }
+ },
+ "firstChannelName": {
+ "type": "string",
+ "description": "Name for the first channel of the team"
+ },
+ "channels": {
+ "type": "array",
+ "description": "Channels to create with the team",
+ "items": {
+ "type": "object",
+ "properties": {
+ "displayName": {
+ "type": "string",
+ "description": "Channel display name"
+ },
+ "description": {
+ "type": "string",
+ "description": "Channel description"
+ },
+ "isFavoriteByDefault": {
+ "type": "boolean",
+ "description": "Whether channel is favorite by default"
+ },
+ "tabs": {
+ "type": "array",
+ "description": "Tabs in the channel",
+ "items": {
+ "type": "object",
+ "properties": {
+ "teamsApp_odata_bind": {
+ "type": "string",
+ "description": "Teams app reference (e.g., 'https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.web')')"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Tab display name"
+ },
+ "configuration": {
+ "type": "object",
+ "description": "Tab configuration",
+ "properties": {
+ "contentUrl": {
+ "type": "string",
+ "description": "Content URL for the tab"
+ },
+ "websiteUrl": {
+ "type": "string",
+ "description": "Website URL for the tab"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "required": [
+ "displayName"
+ ]
+ }
+ },
+ "installedApps": {
+ "type": "array",
+ "description": "Apps to install in the team",
+ "items": {
+ "type": "object",
+ "properties": {
+ "teamsApp_odata_bind": {
+ "type": "string",
+ "description": "Teams app reference (e.g., 'https://graph.microsoft.com/v1.0/appCatalogs/teamsApps('com.microsoft.teamspace.tab.vsts')')"
+ }
+ },
+ "required": [
+ "teamsApp_odata_bind"
+ ]
+ }
+ },
+ "memberSettings": {
+ "type": "object",
+ "description": "Member settings for the team",
+ "properties": {
+ "allowCreateUpdateChannels": {
+ "type": "boolean",
+ "description": "Allow members to create and update channels",
+ "default": true
+ },
+ "allowCreatePrivateChannels": {
+ "type": "boolean",
+ "description": "Allow members to create private channels",
+ "default": true
+ },
+ "allowDeleteChannels": {
+ "type": "boolean",
+ "description": "Allow members to delete channels",
+ "default": true
+ },
+ "allowAddRemoveApps": {
+ "type": "boolean",
+ "description": "Allow members to add and remove apps",
+ "default": true
+ },
+ "allowCreateUpdateRemoveTabs": {
+ "type": "boolean",
+ "description": "Allow members to create, update and remove tabs",
+ "default": true
+ },
+ "allowCreateUpdateRemoveConnectors": {
+ "type": "boolean",
+ "description": "Allow members to create, update and remove connectors",
+ "default": true
+ }
+ }
+ },
+ "guestSettings": {
+ "type": "object",
+ "description": "Guest settings for the team",
+ "properties": {
+ "allowCreateUpdateChannels": {
+ "type": "boolean",
+ "description": "Allow guests to create and update channels",
+ "default": false
+ },
+ "allowDeleteChannels": {
+ "type": "boolean",
+ "description": "Allow guests to delete channels",
+ "default": false
+ }
+ }
+ },
+ "messagingSettings": {
+ "type": "object",
+ "description": "Messaging settings for the team",
+ "properties": {
+ "allowUserEditMessages": {
+ "type": "boolean",
+ "description": "Allow users to edit messages",
+ "default": true
+ },
+ "allowUserDeleteMessages": {
+ "type": "boolean",
+ "description": "Allow users to delete messages",
+ "default": true
+ },
+ "allowOwnerDeleteMessages": {
+ "type": "boolean",
+ "description": "Allow owners to delete messages",
+ "default": true
+ },
+ "allowTeamMentions": {
+ "type": "boolean",
+ "description": "Allow team mentions",
+ "default": true
+ },
+ "allowChannelMentions": {
+ "type": "boolean",
+ "description": "Allow channel mentions",
+ "default": true
+ }
+ }
+ },
+ "funSettings": {
+ "type": "object",
+ "description": "Fun settings for the team",
+ "properties": {
+ "allowGiphy": {
+ "type": "boolean",
+ "description": "Allow Giphy usage",
+ "default": true
+ },
+ "giphyContentRating": {
+ "type": "string",
+ "enum": [
+ "strict",
+ "moderate"
+ ],
+ "description": "Giphy content rating",
+ "default": "moderate"
+ },
+ "allowStickersAndMemes": {
+ "type": "boolean",
+ "description": "Allow stickers and memes",
+ "default": true
+ },
+ "allowCustomMemes": {
+ "type": "boolean",
+ "description": "Allow custom memes",
+ "default": true
+ }
+ }
+ },
+ "discoverySettings": {
+ "type": "object",
+ "description": "Discovery settings for the team",
+ "properties": {
+ "showInTeamsSearchAndSuggestions": {
+ "type": "boolean",
+ "description": "Show in Teams search and suggestions",
+ "default": false
+ }
+ }
+ }
+ },
+ "required": [
+ "template_odata_bind"
+ ],
+ "additionalProperties": true
+ }
+ },
+ {
+ "name": "list_teams",
+ "description": "List all teams in an organization following Microsoft Graph API v1.0. Supports OData query parameters: $filter, $select, $top, $skiptoken, and $count. Returns only id, displayName, and description by default (matching MS Graph API behavior). To get all properties for a specific team, use the get_team tool. API Endpoint: GET /teams",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_top": {
+ "type": "integer",
+ "description": "Number of items to return (max 1000)",
+ "minimum": 1,
+ "maximum": 1000,
+ "default": 50
+ },
+ "_skiptoken": {
+ "type": "string",
+ "description": "Pagination token for retrieving the next page of results"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData filter expression to filter teams. Examples: \"startswith(displayName, 'A')\" - teams starting with A, \"displayName eq 'My Team'\" - exact match, \"contains(displayName, 'Project')\" - teams containing 'Project'",
+ "examples": [
+ "startswith(displayName, 'A')",
+ "displayName eq 'Contoso Team'",
+ "contains(displayName, 'Project')"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return. By default returns id, displayName, description. Examples: 'id,displayName', 'id,description,visibility'",
+ "examples": [
+ "id,displayName",
+ "id,description,visibility"
+ ]
+ },
+ "_count": {
+ "type": "boolean",
+ "description": "Include count of total items in the response",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "update_team",
+ "description": "Update team properties. API Endpoint: PATCH /teams/{team-id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Updated team display name",
+ "maxLength": 255,
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "description": "Updated team description",
+ "maxLength": 1024
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "private",
+ "public",
+ "hiddenMembership"
+ ],
+ "description": "Updated team visibility"
+ },
+ "specialization": {
+ "type": "string",
+ "enum": [
+ "none",
+ "educationStandard",
+ "educationClass",
+ "educationProfessionalLearningCommunity",
+ "educationSpecialInterest",
+ "healthcareStandard",
+ "healthcareCareCoordination",
+ "unknownFutureValue"
+ ],
+ "description": "Updated team specialization"
+ },
+ "memberSettings": {
+ "type": "object",
+ "description": "Updated member settings for the team",
+ "properties": {
+ "allowCreateUpdateChannels": {
+ "type": "boolean",
+ "description": "Allow members to create and update channels"
+ },
+ "allowCreatePrivateChannels": {
+ "type": "boolean",
+ "description": "Allow members to create private channels"
+ },
+ "allowDeleteChannels": {
+ "type": "boolean",
+ "description": "Allow members to delete channels"
+ },
+ "allowAddRemoveApps": {
+ "type": "boolean",
+ "description": "Allow members to add and remove apps"
+ },
+ "allowCreateUpdateRemoveTabs": {
+ "type": "boolean",
+ "description": "Allow members to create, update and remove tabs"
+ },
+ "allowCreateUpdateRemoveConnectors": {
+ "type": "boolean",
+ "description": "Allow members to create, update and remove connectors"
+ }
+ }
+ },
+ "guestSettings": {
+ "type": "object",
+ "description": "Updated guest settings for the team",
+ "properties": {
+ "allowCreateUpdateChannels": {
+ "type": "boolean",
+ "description": "Allow guests to create and update channels"
+ },
+ "allowDeleteChannels": {
+ "type": "boolean",
+ "description": "Allow guests to delete channels"
+ }
+ }
+ },
+ "messagingSettings": {
+ "type": "object",
+ "description": "Updated messaging settings for the team",
+ "properties": {
+ "allowUserEditMessages": {
+ "type": "boolean",
+ "description": "Allow users to edit messages"
+ },
+ "allowUserDeleteMessages": {
+ "type": "boolean",
+ "description": "Allow users to delete messages"
+ },
+ "allowOwnerDeleteMessages": {
+ "type": "boolean",
+ "description": "Allow owners to delete messages"
+ },
+ "allowTeamMentions": {
+ "type": "boolean",
+ "description": "Allow team mentions"
+ },
+ "allowChannelMentions": {
+ "type": "boolean",
+ "description": "Allow channel mentions"
+ }
+ }
+ },
+ "funSettings": {
+ "type": "object",
+ "description": "Updated fun settings for the team",
+ "properties": {
+ "allowGiphy": {
+ "type": "boolean",
+ "description": "Allow Giphy usage"
+ },
+ "giphyContentRating": {
+ "type": "string",
+ "enum": [
+ "strict",
+ "moderate"
+ ],
+ "description": "Giphy content rating"
+ },
+ "allowStickersAndMemes": {
+ "type": "boolean",
+ "description": "Allow stickers and memes"
+ },
+ "allowCustomMemes": {
+ "type": "boolean",
+ "description": "Allow custom memes"
+ }
+ }
+ },
+ "discoverySettings": {
+ "type": "object",
+ "description": "Updated discovery settings for the team",
+ "properties": {
+ "showInTeamsSearchAndSuggestions": {
+ "type": "boolean",
+ "description": "Show in Teams search and suggestions"
+ }
+ }
+ }
+ },
+ "required": [
+ "teamId"
+ ],
+ "minProperties": 2
+ }
+ },
+ {
+ "name": "delete_team",
+ "description": "Delete a team (and its associated Microsoft 365 group). API Endpoint: DELETE /groups/{group-id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier (same as group ID)"
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "list_team_members",
+ "description": "List members of a team following Microsoft Graph API v1.0. This method supports the _filter, _select, and _top OData query parameters to help customize the response. The default and maximum page sizes are 100 and 999 objects respectively. API Endpoint: GET /teams/{team-id}/members",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "REQUIRED. Unique team identifier"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OPTIONAL. OData filter expression to filter team members. Examples: \"(microsoft.graph.aadUserConversationMember/userId eq '73761f06-2ac9-469c-9f10-279a8cc267f9')\" - Filter by userId, \"(microsoft.graph.aadUserConversationMember/displayName eq 'Harry Johnson')\" - Filter by displayName, \"(microsoft.graph.aadUserConversationMember/email eq 'admin@contoso.com')\" - Filter by email, \"(microsoft.graph.aadUserConversationMember/displayName eq 'Harry Johnson' or microsoft.graph.aadUserConversationMember/email eq 'admin@contoso.com')\" - Filter by multiple conditions",
+ "examples": [
+ "(microsoft.graph.aadUserConversationMember/userId eq '73761f06-2ac9-469c-9f10-279a8cc267f9')",
+ "(microsoft.graph.aadUserConversationMember/displayName eq 'Harry Johnson')",
+ "(microsoft.graph.aadUserConversationMember/email eq 'admin@contoso.com')",
+ "(microsoft.graph.aadUserConversationMember/displayName eq 'Harry Johnson' or microsoft.graph.aadUserConversationMember/email eq 'admin@contoso.com')"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "OPTIONAL. Comma-separated list of properties to return. Examples: 'id,roles,displayName,userId,email' - Select specific fields, 'id,displayName' - Select only id and displayName",
+ "examples": [
+ "id,roles,displayName,userId,email",
+ "id,displayName"
+ ]
+ },
+ "_top": {
+ "type": "integer",
+ "description": "OPTIONAL. Number of items per response (default 50, max 999)",
+ "minimum": 1,
+ "maximum": 999,
+ "default": 50
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "add_team_member",
+ "description": "Add a member to a team. API Endpoint: POST /teams/{team-id}/members",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "_odata_type": {
+ "type": "string",
+ "description": "OData type identifier",
+ "default": "#microsoft.graph.aadUserConversationMember"
+ },
+ "roles": {
+ "type": "array",
+ "description": "Member roles in the team",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "member",
+ "guest"
+ ]
+ },
+ "default": [
+ "member"
+ ]
+ },
+ "user_odata_bind": {
+ "type": "string",
+ "description": "User reference (e.g., 'https://graph.microsoft.com/v1.0/users('user-id')')"
+ },
+ "visibleHistoryStartDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp denoting how far back a conversation's history is shared with the member (ISO 8601 format)"
+ }
+ },
+ "required": [
+ "teamId",
+ "user_odata_bind"
+ ]
+ }
+ },
+ {
+ "name": "add_team_members_in_bulk",
+ "description": "Add multiple members to a team in bulk. API Endpoint: POST /teams/{team-id}/members/add",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "values": {
+ "type": "array",
+ "description": "List of members to add",
+ "items": {
+ "type": "object",
+ "properties": {
+ "_odata_type": {
+ "type": "string",
+ "description": "OData type identifier",
+ "default": "#microsoft.graph.aadUserConversationMember"
+ },
+ "roles": {
+ "type": "array",
+ "description": "Member roles in the team",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "member",
+ "guest"
+ ]
+ },
+ "default": [
+ "member"
+ ]
+ },
+ "user_odata_bind": {
+ "type": "string",
+ "description": "User reference (e.g., 'https://graph.microsoft.com/v1.0/users('user-id')')"
+ },
+ "visibleHistoryStartDateTime": {
+ "type": "string",
+ "format": "date-time",
+ "description": "Timestamp denoting how far back a conversation's history is shared with the member"
+ }
+ },
+ "required": [
+ "user_odata_bind"
+ ]
+ },
+ "minItems": 1,
+ "maxItems": 200
+ }
+ },
+ "required": [
+ "teamId",
+ "values"
+ ]
+ }
+ },
+ {
+ "name": "update_team_member",
+ "description": "Update a team member's roles. API Endpoint: PATCH /teams/{team-id}/members/{membership-id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "membershipId": {
+ "type": "string",
+ "description": "Unique membership identifier"
+ },
+ "roles": {
+ "type": "array",
+ "description": "Updated member roles in the team",
+ "items": {
+ "type": "string",
+ "enum": [
+ "owner",
+ "member",
+ "guest"
+ ]
+ },
+ "minItems": 1
+ }
+ },
+ "required": [
+ "teamId",
+ "membershipId",
+ "roles"
+ ]
+ }
+ },
+ {
+ "name": "remove_team_member",
+ "description": "Remove a member from a team. API Endpoint: DELETE /teams/{team-id}/members/{membership-id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "membershipId": {
+ "type": "string",
+ "description": "Unique membership identifier"
+ }
+ },
+ "required": [
+ "teamId",
+ "membershipId"
+ ]
+ }
+ },
+ {
+ "name": "list_installed_apps",
+ "description": "Retrieve the list of apps installed in the specified team. Supports OData query parameters for filtering, expanding, and selecting fields. The id of a teamsAppInstallation is not the same as the id of the teamsApp. API Endpoint: GET /teams/{team-id}/installedApps",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "teamId": {
+ "type": "string",
+ "description": "Unique team identifier"
+ },
+ "_expand": {
+ "type": "string",
+ "description": "Expand related entities. Use 'teamsAppDefinition' to get app version details, 'teamsApp' to get app information, or 'teamsAppDefinition,teamsApp' for both (e.g., 'teamsAppDefinition' or 'teamsApp,teamsAppDefinition')",
+ "examples": [
+ "teamsAppDefinition",
+ "teamsApp",
+ "teamsApp,teamsAppDefinition"
+ ]
+ },
+ "_filter": {
+ "type": "string",
+ "description": "Filter results by app external ID (manifest ID). Use format: teamsApp/externalId eq 'app-external-id'. Note: externalId is empty for store apps; only works for sideloaded/organizational apps (e.g., \"teamsApp/externalId eq 'cf1ba4c7-f94e-4d80-ba90-5594b641a8ee'\")",
+ "examples": [
+ "teamsApp/externalId eq 'cf1ba4c7-f94e-4d80-ba90-5594b641a8ee'"
+ ]
+ },
+ "_select": {
+ "type": "string",
+ "description": "Select specific fields to return. Useful for getting resource-specific permissions. Comma-separated list (e.g., 'consentedPermissionSet,id' or 'id,teamsAppDefinition')",
+ "examples": [
+ "consentedPermissionSet,id",
+ "id"
+ ]
+ }
+ },
+ "required": [
+ "teamId"
+ ]
+ }
+ },
+ {
+ "name": "create_teamwork_tag",
+ "description": "Create a new teamworkTag. API Endpoint: POST /teams/{team_id}/tags",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "team_id": {
+ "type": "string",
+ "description": "ID of the team in which the tag is defined"
+ },
+ "displayName": {
+ "type": "string",
+ "maxLength": 40,
+ "description": "The name of the tag (max 40 characters)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Optional description of the tag"
+ },
+ "members": {
+ "type": "array",
+ "maxItems": 25,
+ "items": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "User ID assigned to the tag"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "Optional display name of the member"
+ }
+ },
+ "required": [
+ "userId"
+ ]
+ },
+ "description": "Members assigned to the tag (max 25 members)"
+ }
+ },
+ "required": [
+ "team_id",
+ "displayName"
+ ]
+ }
+ },
+ {
+ "name": "list_teamwork_tags",
+ "description": "List all teamworkTags. API Endpoint: GET /teams/{team_id}/tags. Supports OData query parameters for filtering and pagination.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "team_id": {
+ "type": "string",
+ "description": "ID of the team to list tags from"
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OData $filter query parameter (e.g., \"tagType eq 'standard'\")"
+ },
+ "_top": {
+ "type": "integer",
+ "description": "OData $top query parameter - number of items to return",
+ "minimum": 1
+ }
+ },
+ "required": [
+ "team_id"
+ ]
+ }
+ },
+ {
+ "name": "update_teamwork_tag",
+ "description": "Update a teamworkTag. API Endpoint: PATCH /teams/{team_id}/tags/{tag_id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "team_id": {
+ "type": "string",
+ "description": "ID of the team containing the tag"
+ },
+ "tag_id": {
+ "type": "string",
+ "description": "Unique teamworkTag identifier"
+ },
+ "displayName": {
+ "type": "string",
+ "maxLength": 40,
+ "description": "Updated name of the tag (max 40 characters)"
+ },
+ "description": {
+ "type": "string",
+ "description": "Updated description of the tag"
+ },
+ "members": {
+ "type": "array",
+ "maxItems": 25,
+ "items": {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ }
+ }
+ },
+ "description": "Updated members list (max 25 members)"
+ }
+ },
+ "required": [
+ "team_id",
+ "tag_id"
+ ]
+ }
+ },
+ {
+ "name": "create_teamwork_tag_member",
+ "description": "Create a new teamworkTagMember - add a user to a teamwork tag. API Endpoint: POST /teams/{team_id}/tags/{tag_id}/members",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "team_id": {
+ "type": "string",
+ "description": "ID of the team containing the tag"
+ },
+ "tag_id": {
+ "type": "string",
+ "description": "ID of the teamwork tag to add member to"
+ },
+ "userId": {
+ "type": "string",
+ "description": "The unique identifier for the member of the team"
+ }
+ },
+ "required": [
+ "team_id",
+ "tag_id",
+ "userId"
+ ]
+ }
+ },
+ {
+ "name": "create_group",
+ "description": "Create a new group following MS Graph API v1.0. Creates a Microsoft Entra group which can be a Microsoft 365 group, a security group, or a distribution group. Supports all writable properties from MS Graph API group resource. Returns 201 Created with group object. API Endpoint: POST /groups",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "displayName": {
+ "type": "string",
+ "description": "REQUIRED. The name to display in the address book for the group. Maximum length: 256 characters. Required.",
+ "maxLength": 256,
+ "minLength": 1
+ },
+ "mailEnabled": {
+ "type": "boolean",
+ "description": "REQUIRED. Set to true for mail-enabled groups. Required."
+ },
+ "mailNickname": {
+ "type": "string",
+ "description": "REQUIRED. The mail alias for the group, unique for Microsoft 365 groups in the organization. Maximum length is 64 characters. This property can contain only characters in the ASCII character set 0 - 127 except: @ () \\ [] \" ; : <> , SPACE. Required.",
+ "maxLength": 64,
+ "minLength": 1
+ },
+ "securityEnabled": {
+ "type": "boolean",
+ "description": "REQUIRED. Set to true for security-enabled groups, including Microsoft 365 groups. Required. Note: Groups created using the Microsoft Entra admin center or the Azure portal always have securityEnabled initially set to true."
+ },
+ "description": {
+ "type": "string",
+ "description": "OPTIONAL. An optional description for the group."
+ },
+ "groupTypes": {
+ "type": "array",
+ "description": "OPTIONAL. Specifies the group type and its membership. If the collection contains 'Unified', the group is a Microsoft 365 group; otherwise, it's either a security group or a distribution group. If the collection includes 'DynamicMembership', the group has dynamic membership; otherwise, membership is static.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "visibility": {
+ "type": "string",
+ "description": "OPTIONAL. Specifies the group join policy and group content visibility for groups. Possible values are: Private, Public, or HiddenMembership. HiddenMembership can be set only for Microsoft 365 groups when the groups are created. It can't be updated later."
+ },
+ "classification": {
+ "type": "string",
+ "description": "OPTIONAL. Describes a classification for the group (such as low, medium or high business impact). Valid values for this property are defined by creating a ClassificationList setting value, based on the template definition."
+ },
+ "assignedLabels": {
+ "type": "array",
+ "description": "OPTIONAL. The list of sensitivity label pairs (label ID, label name) associated with a Microsoft 365 group. Returned only on $select.",
+ "items": {
+ "type": "object"
+ }
+ },
+ "membershipRule": {
+ "type": "string",
+ "description": "OPTIONAL. The rule that determines members for this group if the group is a dynamic group (groupTypes contains DynamicMembership). For more information about the syntax of the membership rule, see Membership Rules syntax."
+ },
+ "membershipRuleProcessingState": {
+ "type": "string",
+ "description": "OPTIONAL. Indicates whether the dynamic membership processing is on or paused. Possible values are On or Paused. Returned only on $select."
+ },
+ "isAssignableToRole": {
+ "type": "boolean",
+ "description": "OPTIONAL. Indicates whether this group can be assigned to a Microsoft Entra role. Optional. This property can only be set while creating the group and is immutable. If set to true, the securityEnabled property must also be set to true, visibility must be Hidden, and the group cannot be a dynamic group (that is, groupTypes cannot contain DynamicMembership). Only callers with at least the Privileged Role Administrator role can set this property. The caller must also be assigned the RoleManagement.ReadWrite.Directory permission to set this property or update the membership of such groups."
+ },
+ "isManagementRestricted": {
+ "type": "boolean",
+ "description": "OPTIONAL. Indicates whether the group is a member of a restricted management administrative unit, in which case it requires a role scoped to the restricted administrative unit to manage. The default value is false. Read-only. To set this value, use the scopedRoleMemberOf navigation property."
+ },
+ "preferredDataLocation": {
+ "type": "string",
+ "description": "OPTIONAL. The preferred data location for the Microsoft 365 group. By default, the group inherits the group creator's preferred data location. To set this property, the calling app must be granted the Directory.ReadWrite.All permission and the user be assigned at least one of the following Microsoft Entra roles: User Account Administrator, Directory Writer, Exchange Administrator, SharePoint Administrator."
+ },
+ "preferredLanguage": {
+ "type": "string",
+ "description": "OPTIONAL. The preferred language for a Microsoft 365 group. Should follow ISO 639-1 Code; for example, en-US. Returned by default."
+ },
+ "resourceBehaviorOptions": {
+ "type": "array",
+ "description": "OPTIONAL. Specifies the group behaviors that can be set for a Microsoft 365 group during creation. This property can be set only as part of creation (POST). For the list of possible values, see Microsoft 365 group behaviors and provisioning options.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "resourceProvisioningOptions": {
+ "type": "array",
+ "description": "OPTIONAL. Specifies the group resources that are associated with the Microsoft 365 group. The possible value is Team. For more information, see Microsoft 365 group behaviors and provisioning options. Returned by default.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "theme": {
+ "type": "string",
+ "description": "OPTIONAL. Specifies a Microsoft 365 group's color theme. Possible values are Teal, Purple, Green, Blue, Pink, Orange or Red. Returned by default."
+ },
+ "owners_odata_bind": {
+ "type": "array",
+ "description": "OPTIONAL. List of owner references in OData format. Format: ['https://graph.microsoft.com/v1.0/users/{id}', ...]. During group creation, the owner(s) should be specified using this property.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "members_odata_bind": {
+ "type": "array",
+ "description": "OPTIONAL. List of member references in OData format. Format: ['https://graph.microsoft.com/v1.0/users/{id}', ...]. During group creation, members can be added using this property. Maximum of 20 members can be added during group creation.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "displayName",
+ "mailEnabled",
+ "mailNickname",
+ "securityEnabled"
+ ]
+ }
+ },
+ {
+ "name": "list_groups",
+ "description": "List groups in the organization. Per Microsoft Graph API documentation: Supports _count, _expand, _filter, _orderby, _search, _select, and _top OData query parameters. NOTE: _skip is NOT supported. The $search query parameter supports tokenization only on displayName and description fields. Fields other than displayName and description default to _filter startswith behavior. API Endpoint: GET /groups",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_top": {
+ "type": "integer",
+ "description": "OPTIONAL. Number of items per response (max 999, default 100)",
+ "minimum": 1,
+ "maximum": 999,
+ "default": 100
+ },
+ "_filter": {
+ "type": "string",
+ "description": "OPTIONAL. OData filter expression. Examples: \"displayName eq 'Marketing'\", \"securityEnabled eq true\", \"startswith(displayName, 'Sales')\", \"mailEnabled eq true and securityEnabled eq false\""
+ },
+ "_select": {
+ "type": "string",
+ "description": "OPTIONAL. Comma-separated list of properties to return. Schema extensions are returned only with _select. Example: 'id,displayName,mail,visibility'"
+ },
+ "_orderby": {
+ "type": "string",
+ "description": "OPTIONAL. Order results by properties. Examples: 'displayName asc', 'createdDateTime desc'"
+ },
+ "_search": {
+ "type": "string",
+ "description": "OPTIONAL. Search query. Supports tokenization only on displayName and description fields. Other fields default to _filter startswith behavior. Example: '\"Marketing\"'"
+ },
+ "_count": {
+ "type": "boolean",
+ "description": "OPTIONAL. Include count of total matching results in response"
+ },
+ "_expand": {
+ "type": "string",
+ "description": "OPTIONAL. Expand related entities. Open extensions are returned only with _expand. Example: 'members'"
+ }
+ }
+ }
+ },
+ {
+ "name": "update_group",
+ "description": "Update group properties. Only updates the properties provided in the request. API Endpoint: PATCH /groups/{id}",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "groupId": {
+ "type": "string",
+ "description": "REQUIRED. Unique group identifier"
+ },
+ "allowExternalSenders": {
+ "type": "boolean",
+ "description": "OPTIONAL. Default is false. Indicates whether people external to the organization can send messages to the group."
+ },
+ "assignedLabels": {
+ "type": "array",
+ "description": "OPTIONAL. The list of sensitivity label pairs (label ID, label name) associated with a Microsoft 365 group. This property can be updated only in delegated scenarios where the caller requires both the Microsoft Graph permission and a supported administrator role.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "labelId": {
+ "type": "string",
+ "description": "The unique identifier of the label"
+ },
+ "displayName": {
+ "type": "string",
+ "description": "The display name of the label"
+ }
+ }
+ }
+ },
+ "autoSubscribeNewMembers": {
+ "type": "boolean",
+ "description": "OPTIONAL. Default is false. Indicates whether new members added to the group will be auto-subscribed to receive email notifications. autoSubscribeNewMembers can't be true when subscriptionEnabled is set to false on the group."
+ },
+ "description": {
+ "type": "string",
+ "description": "OPTIONAL. An optional description for the group."
+ },
+ "displayName": {
+ "type": "string",
+ "description": "OPTIONAL. The display name for the group. This property is required when a group is created and it cannot be cleared during updates.",
+ "maxLength": 255,
+ "minLength": 1
+ },
+ "mailNickname": {
+ "type": "string",
+ "description": "OPTIONAL. The mail alias for the group, unique for Microsoft 365 groups in the organization. Maximum length is 64 characters. This property can contain only characters in the ASCII character set 0 - 127 except the following: @ () \\ [] \" ; : . <> , SPACE.",
+ "maxLength": 64
+ },
+ "preferredDataLocation": {
+ "type": "string",
+ "description": "OPTIONAL. The preferred data location for the Microsoft 365 group. To update this property, the calling user must be assigned at least one of the following Microsoft Entra roles: User Account Administrator, Directory Writer, Exchange Administrator, SharePoint Administrator. For more information about this property, see OneDrive Online Multi-Geo."
+ },
+ "securityEnabled": {
+ "type": "boolean",
+ "description": "OPTIONAL. Specifies whether the group is a security group."
+ },
+ "uniqueName": {
+ "type": "string",
+ "description": "OPTIONAL. The unique identifier that can be assigned to a group and used as an alternate key. Can updated only if null and is immutable once set."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "Private",
+ "Public",
+ "Hiddenmembership"
+ ],
+ "description": "OPTIONAL. Specifies the visibility of a Microsoft 365 group. The possible values are: Private, Public, or empty (which is interpreted as Public)."
+ }
+ },
+ "required": [
+ "groupId"
+ ],
+ "minProperties": 2
+ }
+ },
+ {
+ "name": "add_group_owner",
+ "description": "Add an owner to a group. Returns 204 No Content on success. API Endpoint: POST /groups/{id}/owners/$ref",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "groupId": {
+ "type": "string",
+ "description": "REQUIRED. Unique group identifier"
+ },
+ "_odata_id": {
+ "type": "string",
+ "description": "REQUIRED. OData reference to the owner user (e.g., 'https://graph.microsoft.com/v1.0/users/{user-id}')"
+ }
+ },
+ "required": [
+ "groupId",
+ "_odata_id"
+ ]
+ }
+ },
+ {
+ "name": "list_call_records",
+ "description": "Get the list of callRecord objects and their properties.\n\n API Endpoint: GET /communications/callRecords\n\n Permissions (Application ONLY - Delegated NOT supported):\n - CallRecords.Read.All (required)\n\n Important Notes:\n - Delegated permissions are NOT supported - only application permissions allowed\n - A call record is created after a call or meeting ends and remains available for 30 days\n - This API doesn't return call records older than 30 days\n - Listed call records don't include expandable relationships (sessions, participants_v2)\n - Default page size: 60 entries\n - Admin consent required\n\n Response includes:\n - @odata.context: OData context URL\n - @odata.nextLink: URL for next page if more results available\n - value: Array of callRecord objects with:\n - id: Unique identifier\n - version: Version number (typically 2)\n - type: Type of call (unknown, groupCall, peerToPeer)\n - modalities: List of modalities (audio, video, videoBasedScreenSharing, data)\n - lastModifiedDateTime: Last modified timestamp\n - startDateTime: Call start timestamp\n - endDateTime: Call end timestamp\n - organizer: Organizer identity information\n - organizer_v2: Newer format organizer with full identity\n\n Available in national cloud deployments:\n - Global service\n - US Government L4\n - US Government L5 (DOD)\n - China operated by 21Vianet\n\n Reference: https://learn.microsoft.com/en-us/graph/api/callrecords-cloudcommunications-list-callrecords",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_filter": {
+ "type": "string",
+ "description": "Filter query parameter. Supported filters:\n\n 1. startDateTime (supports: lt, le, gt, ge)\n Example: \"startDateTime ge 2023-09-25T09:25:00Z and startDateTime lt 2023-09-25T09:30:00Z\"\n\n 2. participants_v2.id (supports: eq)\n Example: \"participants_v2/any(p:p/id eq '821809f5-0000-0000-0000-3b5136c0e777')\"\n\n Note: Only these two filter properties are supported."
+ },
+ "_select": {
+ "type": "string",
+ "description": "Select specific properties to return.\n\n Example: \"id,startDateTime,endDateTime,modalities\"\n\n Available properties: id, version, type, modalities, lastModifiedDateTime, startDateTime, endDateTime, organizer, organizer_v2"
+ }
+ }
+ }
+ },
+ {
+ "name": "get_call_record",
+ "description": "Retrieve the properties and relationships of a callRecord object.\n\n API Endpoint: GET /communications/callRecords/{id}\n\n Permissions (Application ONLY - Delegated NOT supported):\n - CallRecords.Read.All (required)\n\n Important Notes:\n - Delegated permissions are NOT supported - only application permissions allowed\n - A call record is created after a call or meeting ends and remains available for 30 days\n - This API doesn't return call records older than 30 days\n - Requests for records older than 30 days result in 404 Not Found\n - Admin consent required\n\n How to get call record ID:\n 1. Subscribe to change notifications to /communications/callRecords endpoint\n 2. Use the callChainId property of a call (record available after call completes)\n\n Query Parameters:\n - _select: Return specific properties (e.g., \"id,startDateTime,endDateTime,modalities\")\n - _expand: Include relationships:\n - participants_v2: Expand full participant list (max 130 entries per page)\n - sessions(_expand=segments): Expand sessions with their segments (max 60 sessions per page)\n\n Response includes:\n - id: Unique identifier\n - version: Version number\n - type: Call type (peerToPeer, groupCall, unknown)\n - modalities: Array of modalities (audio, video, videoBasedScreenSharing, data)\n - lastModifiedDateTime: Last modified timestamp\n - startDateTime: Call start timestamp\n - endDateTime: Call end timestamp\n - organizer_v2: Organizer identity with full details\n - participants_v2: Array of participants (when expanded)\n - sessions: Array of session objects (when expanded)\n Request Headers (optional):\n - Prefer: odata.maxpagesize={x} - Preferred page size for paginated results\n - Prefer: include-unknown-enum-members - Enable evolvable enum values\n - Prefer: omit-values=nulls - Remove null/empty values from response\n Available in national cloud deployments:\n - Global service\n - US Government L4\n - US Government L5 (DOD)\n - China operated by 21Vianet\n Reference: https://learn.microsoft.com/en-us/graph/api/callrecords-callrecord-get",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The unique identifier of the call record to retrieve"
+ },
+ "_select": {
+ "type": "string",
+ "description": "Select specific properties to return.\n\n Example: \"id,startDateTime,endDateTime,modalities\"\n\n Available properties: id, version, type, modalities, lastModifiedDateTime, startDateTime, endDateTime, organizer_v2\n\n Note: Only supported for callRecord and session resources."
+ },
+ "_expand": {
+ "type": "string",
+ "description": "Expand relationships to include in the response.\n\n Examples:\n - \"participants_v2\" - Include full participant list (paginated, max 130 per page)\n - \"sessions(_expand=segments)\" - Include sessions with their segments (max 60 sessions per page)\n\n Available relationships:\n - participants_v2: Participant details\n - sessions: Session details (can further expand segments)"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "list_call_sessions",
+ "description": "Retrieve the list of sessions associated with a callRecord object.\n\n API Endpoint: GET /communications/callRecords/{id}/sessions\n\n Permissions (Application ONLY - Delegated NOT supported):\n - CallRecords.Read.All (required)\n\n Important Notes:\n - Delegated permissions are NOT supported - only application permissions allowed\n - A call record is created after a call or meeting ends and remains available for 30 days\n - Sessions provide detailed information about peer-to-peer and group calls\n - Maximum page size: 60 sessions per page\n - Supports _expand parameter to include segments within sessions\n - Admin consent required\n\n Response includes:\n - @odata.context: OData context URL\n - @odata.nextLink: URL for next page if more than 60 sessions\n - value: Array of session objects with:\n - id: Unique identifier for the session\n - caller: Endpoint that initiated the session\n - callee: Endpoint that answered the session\n - failureInfo: Failure information if session failed\n - modalities: List of modalities (audio, video, videoBasedScreenSharing, data, screenSharing, unknownFutureValue)\n - startDateTime: UTC time when first user joined the session\n - endDateTime: UTC time when last user left the session\n - segments: Media streams between endpoints (when expanded)\n\n Query Parameters:\n - _select: Return specific properties (e.g., \"id,startDateTime,endDateTime\")\n - _expand: Include segments - \"segments\" or \"segments(_select=id)\"\n\n Available in national cloud deployments:\n - Global service\n - US Government L4\n - US Government L5 (DOD)\n - China operated by 21Vianet\n Reference: https://learn.microsoft.com/en-us/graph/api/callrecords-callrecord-list-sessions",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The unique identifier of the call record"
+ },
+ "_select": {
+ "type": "string",
+ "description": "Optional OData _select parameter to return specific properties (e.g., 'id,startDateTime,endDateTime,modalities')"
+ },
+ "_expand": {
+ "type": "string",
+ "description": "Optional OData _expand parameter to include segments. Use 'segments' to include all segment properties, or 'segments(_select=id)' to select specific segment properties"
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ {
+ "name": "create_call",
+ "description": "Create a new outgoing peer-to-peer or group call, or join an existing meeting.\n\nSupported scenarios:\n- Peer-to-peer VoIP calls (service or app-hosted media)\n- Group calls with up to 5 VoIP users\n- PSTN calls (requires application instance with PSTN number)\n- Join scheduled meetings (using chatInfo and meetingInfo)\n- Join meetings with joinMeetingId and optional passcode\n\nPermissions (Application only):\n- Calls.JoinGroupCalls.Chat (least privileged for joining meetings)\n- Calls.Initiate.All (for peer-to-peer calls)\n- Calls.InitiateGroupCall.All (for group calls)\n- Calls.JoinGroupCall.All (for joining meetings)\n- Calls.JoinGroupCallAsGuest.All\n- Calls.AccessMedia.All (required for app-hosted media)\n\nNote: Delegated permissions are not supported for this API.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "callbackUri": {
+ "type": "string",
+ "description": "HTTPS callback URL for notifications (required)"
+ },
+ "source": {
+ "type": "object",
+ "description": "Source participant info (optional, for PSTN calls with applicationInstance)",
+ "properties": {
+ "identity": {
+ "type": "object",
+ "properties": {
+ "applicationInstance": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "targets": {
+ "type": "array",
+ "description": "Target participants for peer-to-peer or group calls (max 5). Do not use with meetingInfo.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "identity": {
+ "type": "object",
+ "description": "Participant identity (user or phone)",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ }
+ }
+ },
+ "phone": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Phone number in E.164 format"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "requestedModalities": {
+ "type": "array",
+ "description": "Requested modalities (required)",
+ "items": {
+ "type": "string",
+ "enum": [
+ "audio",
+ "video",
+ "videoBasedScreenSharing",
+ "data"
+ ]
+ }
+ },
+ "callOptions": {
+ "type": "object",
+ "description": "Call options",
+ "properties": {
+ "isContentSharingNotificationEnabled": {
+ "type": "boolean"
+ },
+ "isDeltaRosterEnabled": {
+ "type": "boolean"
+ },
+ "isInteractiveRosterEnabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "mediaConfig": {
+ "type": "object",
+ "description": "Media configuration (required). Must include _odata_type",
+ "properties": {
+ "_odata_type": {
+ "type": "string",
+ "enum": [
+ "#microsoft.graph.serviceHostedMediaConfig",
+ "#microsoft.graph.appHostedMediaConfig"
+ ],
+ "description": "Type of media configuration"
+ },
+ "preFetchMedia": {
+ "type": "array",
+ "description": "Media to pre-fetch (for service-hosted)",
+ "items": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "resourceId": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "blob": {
+ "type": "string",
+ "description": "Media session configuration blob (for app-hosted)"
+ },
+ "removeFromDefaultAudioGroup": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "_odata_type"
+ ]
+ },
+ "chatInfo": {
+ "type": "object",
+ "description": "Chat information for joining meetings (use with meetingInfo)",
+ "properties": {
+ "threadId": {
+ "type": "string"
+ },
+ "messageId": {
+ "type": "string"
+ }
+ }
+ },
+ "meetingInfo": {
+ "type": "object",
+ "description": "Meeting information for joining meetings. Do not use with targets.",
+ "properties": {
+ "_odata_type": {
+ "type": "string",
+ "enum": [
+ "#microsoft.graph.organizerMeetingInfo",
+ "#microsoft.graph.joinMeetingIdMeetingInfo",
+ "#microsoft.graph.tokenMeetingInfo"
+ ]
+ },
+ "organizer": {
+ "type": "object",
+ "description": "For organizerMeetingInfo",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "displayName": {
+ "type": "string"
+ },
+ "tenantId": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "allowConversationWithoutHost": {
+ "type": "boolean"
+ },
+ "joinMeetingId": {
+ "type": "string",
+ "description": "For joinMeetingIdMeetingInfo"
+ },
+ "passcode": {
+ "type": "string",
+ "description": "Optional passcode for joinMeetingIdMeetingInfo"
+ }
+ }
+ },
+ "subject": {
+ "type": "string",
+ "description": "Call subject"
+ },
+ "tenantId": {
+ "type": "string",
+ "description": "Tenant ID"
+ }
+ },
+ "required": [
+ "callbackUri",
+ "requestedModalities",
+ "mediaConfig"
+ ]
+ }
+ },
+ {
+ "name": "create_audio_routing_group",
+ "description": "Create a new audio routing group for a call.\n\nThe audio routing group stores a private audio route between participants in a\nmultiparty conversation. Source is the participant itself and the receivers are\na subset of other participants in the multiparty conversation.\n\nIMPORTANT NOTES:\n- **PERMISSION REQUIRED**: Application-only permission (NO delegated)\n - Calls.JoinGroupCall.All (least privileged)\n - Calls.InitiateGroupCall.All (higher privileged)\n- **4-speaker limit**: Only top 4 dominant speakers' audio forwarded in group calls\n- If speaker not loud enough in main mixer, bot won't hear even with private audio group\n\nROUTING MODES:\n1. **oneToOne** (1 source \u2194 1 receiver):\n - Immutable after creation (cannot be updated)\n - Exactly 1 source participant required\n - Exactly 1 receiver participant required\n - For private 1-to-1 audio channel\n\n2. **multicast** (1 source \u2192 multiple receivers):\n - Source has 1 participant\n - Multiple receivers allowed\n - Receiver list can be updated later\n - Useful for broadcast scenarios\n\nCRITICAL VALIDATION RULES (Per Microsoft Graph API):\n- Sources must have exactly 1 participant ID (the authenticated bot/application)\n- Source participant MUST be the authenticated bot making the API call\n- Receivers must have at least 1 participant ID\n- Routing mode MUST match participant count:\n * 1 source + 1 receiver \u2192 MUST use \"oneToOne\" mode\n * 1 source + 2+ receivers \u2192 MUST use \"multicast\" mode\n- Parent call must be in active state (not terminated/terminating)\n- All participants must exist in the call and belong to same organization\n\nPermissions (Application only):\n- Calls.JoinGroupCall.All (least privileged)\n- Calls.InitiateGroupCall.All (higher privileged)\n\nNote: Delegated permissions are NOT supported.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "call_id": {
+ "type": "string",
+ "description": "Parent call ID (required)"
+ },
+ "routingMode": {
+ "type": "string",
+ "enum": [
+ "oneToOne",
+ "multicast"
+ ],
+ "description": "Routing mode: oneToOne (immutable) or multicast (updatable receivers)"
+ },
+ "sources": {
+ "type": "array",
+ "description": "Source participant IDs (must have exactly 1 participant - the authenticated bot/application making this API call)",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "maxItems": 1
+ },
+ "receivers": {
+ "type": "array",
+ "description": "Receiver participant IDs. For oneToOne mode: exactly 1 receiver. For multicast mode: 2 or more receivers.",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1
+ }
+ },
+ "required": [
+ "call_id",
+ "routingMode",
+ "sources",
+ "receivers"
+ ]
+ }
+ },
+ {
+ "name": "set_user_status_message",
+ "description": "Set a user's status message.\n\n Sets the state of a user's status message following Microsoft Graph API v1.0 structure.\n This endpoint corresponds to POST /users/{id}/presence/setStatusMessage in Microsoft Graph API.\n\n The status message is displayed in Microsoft Teams and other applications that support\n presence information. This provides users with a way to communicate additional context\n about their current status beyond just availability and activity.\n\n Request Parameters:\n - user_id: Required. User identifier - accepts either user ID (UUID) or userPrincipalName\n - statusMessage: Required. Object containing status message details\n * message: Required. The status message text (maximum 280 characters)\n * expiryDateTime: Optional. Object containing dateTime and timeZone when the status message expires\n\n Status Message Behavior:\n - Displayed across Microsoft Teams and other presence-aware applications\n - If no expiry time is set, the message persists until manually cleared\n - Maximum message length is 280 characters (same as Microsoft Teams)\n - Empty or null message will clear the existing status message\n - Status message is independent of presence availability and activity\n\n Use Cases:\n - \"In a meeting until 3pm\"\n - \"Working from home today\"\n - \"Back in 30 minutes\"\n - \"Focus time - please use email\"\n - \"On vacation until next Monday\"\n\n Response:\n - Returns 200 OK with empty response body on successful operation\n - Follows Microsoft Graph API v1.0 response format\n\n Authentication:\n - Requires x-teams-access-token header with valid access token\n - Token will be validated against user database\n\n Permissions Required:\n - Presence.ReadWrite:delegated (can set own status message)\n - Presence.ReadWrite.All:application (can set any user's status message)\n\n Status Codes:\n - 200: Success - Status message set successfully\n - 400: Bad Request - Invalid message or malformed request\n - 401: Unauthorized - Invalid or missing access token\n - 403: Forbidden - Insufficient permissions\n - 404: Not Found - User not found\n - 500: Internal Server Error\n\n Microsoft Graph Documentation:\n https://learn.microsoft.com/en-us/graph/api/presence-setstatusmessage",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": "string",
+ "description": "User identifier - accepts either user ID (UUID) or userPrincipalName (e.g., 'alice_manager')",
+ "minLength": 1,
+ "maxLength": 320
+ },
+ "statusMessage": {
+ "type": "object",
+ "description": "Status message object containing message details",
+ "properties": {
+ "message": {
+ "type": "object",
+ "description": "Message object with content and contentType",
+ "properties": {
+ "content": {
+ "type": "string",
+ "description": "The status message text (maximum 280 characters)",
+ "maxLength": 280
+ },
+ "contentType": {
+ "type": "string",
+ "description": "Content type (must be 'text')",
+ "enum": [
+ "text"
+ ]
+ }
+ },
+ "required": [
+ "content",
+ "contentType"
+ ],
+ "additionalProperties": false
+ },
+ "expiryDateTime": {
+ "type": "object",
+ "description": "Expiry date and time information for the status message",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "The date and time in ISO 8601 format",
+ "format": "date-time",
+ "examples": [
+ "2022-10-18T17:05:33.2079781",
+ "2024-01-15T09:00:00.000Z"
+ ]
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "The time zone of the dateTime",
+ "examples": [
+ "Pacific Standard Time",
+ "UTC",
+ "Eastern Standard Time"
+ ]
+ }
+ },
+ "required": [
+ "dateTime",
+ "timeZone"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "message"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "user_id",
+ "statusMessage"
+ ]
+ }
+ },
+ {
+ "name": "create_virtual_event_webinar",
+ "description": "Create a new virtualEventWebinar object in draft mode.\n\n API Endpoint: POST /solutions/virtualEvents/webinars\n\n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): VirtualEvent.ReadWrite (least privileged)\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: NOT SUPPORTED\n\n CRITICAL: Only delegated permissions with work/school account are supported.\n Application permissions are explicitly not supported for this API.\n\n Request Body Properties (all following Microsoft Graph API v1.0 spec):\n - displayName (required): The display name of the webinar (1-500 characters)\n - description (required): A description with:\n - contentType: 'text' or 'html'\n - content: The description text\n - startDateTime (required): Start date-time with:\n - dateTime: ISO 8601 format (e.g., '2024-03-30T10:00:00')\n - timeZone: Timezone name (e.g., 'Pacific Standard Time')\n - endDateTime (required): End date-time (must be after startDateTime) with:\n - dateTime: ISO 8601 format\n - timeZone: Timezone name\n - audience (required): Webinar visibility\n - Possible values: 'everyone', 'organization', 'unknownFutureValue'\n - coOrganizers (optional): Array of user identities, each with:\n - id: User ID (required) - displayName and tenantId are auto-populated from database\n - settings (optional): Webinar settings with:\n - isAttendeeEmailNotificationEnabled: Boolean (default: false)\n\n Response Properties:\n - id: Unique identifier (format: guid@guid)\n - status: Webinar status (always 'draft' on creation)\n - displayName, description, startDateTime, endDateTime, audience: From request\n - createdBy: Creator identity information (auto-populated from authenticated user)\n - application: null\n - device: null\n - user: User identity with @odata.type, id, displayName, tenantId\n - coOrganizers: Array of coorganizer identities (with displayName populated)\n - settings: Webinar settings\n - externalEventInformation: Empty array initially\n\n Important Notes:\n - Webinars are always created in 'draft' status\n - Only delegated permissions supported (no application permissions)\n - Personal Microsoft accounts are NOT supported\n - endDateTime must be after startDateTime\n - CoOrganizers must exist in the system\n - Creator information is auto-populated from authenticated user\n\n Available in national cloud deployments:\n - Global service \n - US Government L4 \n - US Government L5 (DOD) \n - China operated by 21Vianet (status unknown)\n\n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventsroot-post-webinars",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "displayName": {
+ "type": "string",
+ "description": "The display name of the webinar (required, 1-500 characters)"
+ },
+ "description": {
+ "type": "object",
+ "description": "Description of the webinar (required)",
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "Content type: 'text' or 'html' (default: 'text')"
+ },
+ "content": {
+ "type": "string",
+ "description": "Description content"
+ }
+ },
+ "required": [
+ "contentType",
+ "content"
+ ]
+ },
+ "startDateTime": {
+ "type": "object",
+ "description": "Start date and time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "ISO 8601 date-time string (e.g., '2024-03-30T10:00:00')"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Windows timezone name (e.g., 'Pacific Standard Time', 'UTC', 'Eastern Standard Time'). IMPORTANT: Only Windows timezone names are supported, NOT IANA timezones like 'America/New_York'."
+ }
+ },
+ "required": [
+ "dateTime",
+ "timeZone"
+ ]
+ },
+ "endDateTime": {
+ "type": "object",
+ "description": "End date and time (required, must be after startDateTime)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "ISO 8601 date-time string (e.g., '2024-03-30T17:00:00')"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Windows timezone name (e.g., 'Pacific Standard Time', 'UTC', 'Eastern Standard Time'). IMPORTANT: Only Windows timezone names are supported, NOT IANA timezones like 'America/New_York'."
+ }
+ },
+ "required": [
+ "dateTime",
+ "timeZone"
+ ]
+ },
+ "audience": {
+ "type": "string",
+ "enum": [
+ "everyone",
+ "organization",
+ "unknownFutureValue"
+ ],
+ "description": "Audience visibility (required). Use 'organization' for internal webinars, 'everyone' for public."
+ },
+ "coOrganizers": {
+ "type": "array",
+ "description": "Coorganizers of the webinar (optional). Each coorganizer must exist in the system. Only user ID is required - displayName and tenantId are auto-populated from the database.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User ID of coorganizer (required). Display name and tenant ID will be auto-populated from the user's database record."
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ "settings": {
+ "type": "object",
+ "description": "Webinar settings (optional)",
+ "properties": {
+ "isAttendeeEmailNotificationEnabled": {
+ "type": "boolean",
+ "description": "Enable attendee email notifications (default: false)"
+ }
+ }
+ }
+ },
+ "required": [
+ "displayName",
+ "description",
+ "startDateTime",
+ "endDateTime",
+ "audience"
+ ]
+ }
+ },
+ {
+ "name": "get_virtual_event_webinar",
+ "description": "Get a virtualEventWebinar object by ID.\n\n API Endpoint: GET /solutions/virtualEvents/webinars/{webinarId}\n\n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): VirtualEvent.Read OR VirtualEvent.ReadWrite\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: VirtualEvent.Read.All\n\n All roles can get the details of a webinar event.\n\n Request Parameters:\n - webinar_id (required): The unique identifier of the webinar (format: guid@guid)\n Example: \"88b245ac-b0b2-f1aa-e34a-c81c27abdac2@f9448ec4-804b-46af-b810-62085248da33\"\n\n Response Properties:\n - id: Unique identifier (format: guid@guid)\n - status: Webinar status (draft, published, canceled, unknownFutureValue)\n - displayName: Display name of the webinar\n - description: Description with contentType and content\n - startDateTime: Start date-time with timezone\n - endDateTime: End date-time with timezone\n - audience: Audience visibility (everyone, organization, unknownFutureValue)\n - createdBy: Creator identity information\n - application: null\n - device: null\n - user: User identity with @odata.type, id, displayName, tenantId\n - coOrganizers: Array of coorganizer identities\n - settings: Webinar settings\n - externalEventInformation: External event information (only for organizers/coorganizers)\n\n Important Notes:\n - Webinar ID must be in format: guid@guid\n - Returns 404 if webinar doesn't exist\n - Returns direct webinar object (not wrapped in \"value\" field)\n\n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventwebinar-get",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "webinar_id": {
+ "type": "string",
+ "description": "The unique identifier of the webinar (required, format: guid@guid). Example: '88b245ac-b0b2-f1aa-e34a-c81c27abdac2@f9448ec4-804b-46af-b810-62085248da33'"
+ }
+ },
+ "required": [
+ "webinar_id"
+ ]
+ }
+ },
+ {
+ "name": "list_virtual_event_webinars",
+ "description": "Get the list of all virtualEventWebinar objects created in a tenant.\n\n API Endpoint: GET /solutions/virtualEvents/webinars\n\n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): VirtualEvent.Read OR VirtualEvent.ReadWrite\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: VirtualEvent.Read.All (least privileged)\n\n Optional Query Parameters:\n - _count: Include total count of items (boolean). Maps to $count query parameter.\n When true, response includes @odata.count field with total number of webinars.\n\n Response Properties:\n - value: Array of virtualEventWebinar objects\n - @odata.count: Total count of webinars (only if _count=true)\n\n Each webinar object in the array includes:\n - id: Unique identifier (format: guid@guid)\n - status: Webinar status (draft, published, canceled, unknownFutureValue)\n - displayName, description, startDateTime, endDateTime, audience\n - createdBy: Creator identity information\n - coOrganizers: Array of coorganizer identities\n - settings: Webinar settings\n - externalEventInformation: External event information (only for organizers/coorganizers)\n\n Important Notes:\n - Returns webinars from the authenticated user's organization only\n - Default limit of 100 webinars\n - Use _count=true to get total count in response\n\n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventsroot-list-webinars",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_count": {
+ "type": "boolean",
+ "description": "Include total count in response (@odata.count). Maps to $count query parameter. Set to true to include count, false or omit to exclude.",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "publish_virtual_event_webinar",
+ "description": "Publish a virtualEventWebinar to make it visible to its audience.\n \n CRITICAL: Only the Organizer (creator) can publish a webinar.\n Co-organizers CANNOT publish (unlike the UPDATE API).\n \n **Action:** Changes webinar status from 'draft' to 'published'\n \n **Status Transitions:**\n - draft \u2192 published (allowed, returns 204 No Content)\n - published \u2192 published (idempotent, returns 204 No Content)\n - canceled \u2192 published (error: cannot publish canceled webinar, returns 400)\n \n **Permissions Required:**\n - VirtualEvent.ReadWrite:delegated (only delegated, NOT application)\n \n **Response:** 204 No Content on success (no response body)\n \n **Authorization:**\n - ONLY the Organizer can publish\n - Co-organizers are NOT allowed to publish\n - Non-organizers will receive 403 Forbidden\n \n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventwebinar-publish\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "webinar_id": {
+ "type": "string",
+ "description": "Unique identifier of the webinar (format: guid@guid). Example: 'a57082a9-7629-4f74-8da0-8d621aab4d2d@4aa05bcc-1cac-4a83-a9ae-0db84b88f4ba'"
+ }
+ },
+ "required": [
+ "webinar_id"
+ ]
+ }
+ },
+ {
+ "name": "cancel_virtual_event_webinar",
+ "description": "Cancel a virtualEventWebinar. A canceled webinar has its status set to canceled permanently.\n \n CRITICAL: Only the Organizer (creator) can cancel a webinar.\n Co-organizers CANNOT cancel.\n \n **Action:** Changes webinar status to 'canceled' permanently\n \n **Status Transitions:**\n - draft \u2192 canceled (allowed, returns 204 No Content)\n - published \u2192 canceled (allowed, returns 204 No Content)\n - canceled \u2192 canceled (idempotent, returns 204 No Content)\n \n **Permissions Required:**\n - VirtualEvent.ReadWrite:delegated (only delegated, NOT application)\n \n **Response:** 204 No Content on success (no response body)\n \n **Authorization:**\n - ONLY the Organizer can cancel\n - Co-organizers are NOT allowed to cancel\n - Non-organizers will receive 403 Forbidden\n \n **Note:** You can still get a canceled webinar using the Get virtualEventWebinar API.\n \n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventwebinar-cancel\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "webinar_id": {
+ "type": "string",
+ "description": "Unique identifier of the webinar (format: guid@guid). Example: 'a57082a9-7629-4f74-8da0-8d621aab4d2d@4aa05bcc-1cac-4a83-a9ae-0db84b88f4ba'"
+ }
+ },
+ "required": [
+ "webinar_id"
+ ]
+ }
+ },
+ {
+ "name": "create_virtual_event_townhall",
+ "description": "Create a new virtualEventTownhall object in draft mode.\n\n API Endpoint: POST /solutions/virtualEvents/townhalls\n\n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): VirtualEvent.ReadWrite (least privileged)\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: NOT SUPPORTED\n\n CRITICAL: Only delegated permissions with work/school account are supported.\n\n CRITICAL CONSTRAINT: The isInviteOnly property can ONLY be true if the audience property is set to 'organization'.\n\n Request Body Properties (all following Microsoft Graph API v1.0 spec):\n - displayName (required): The display name of the townhall (1-500 characters)\n - description (required): A description with:\n - contentType: 'text' or 'html'\n - content: The description text\n - startDateTime (required): Start date-time with:\n - dateTime: ISO 8601 format (e.g., '2024-03-30T10:00:00')\n - timeZone: Timezone name (e.g., 'Pacific Standard Time')\n - endDateTime (required): End date-time (must be after startDateTime) with:\n - dateTime: ISO 8601 format\n - timeZone: Timezone name\n - audience (required): Townhall visibility\n - Possible values: 'everyone', 'organization', 'unknownFutureValue'\n - isInviteOnly (optional): Whether townhall is invite-only (default: false)\n - Can ONLY be true if audience='organization'\n - invitedAttendees (optional): Array of user/guest identities, each with:\n - id: User/Guest ID (required)\n - email: Email for guest identities (optional, if provided identifies as guest)\n - displayName: Display name (optional, auto-populated for users)\n - coOrganizers (optional): Array of user identities, each with:\n - id: User ID (required)\n - tenantId: Tenant ID (required) - displayName auto-populated from database\n - settings (optional): Townhall settings with:\n - isAttendeeEmailNotificationEnabled: Boolean (default: false)\n\n Response Properties:\n - id: Unique identifier (format: guid@guid)\n - status: Townhall status (always 'draft' on creation)\n - displayName, description, startDateTime, endDateTime, audience: From request\n - isInviteOnly: From request (default: false)\n - invitedAttendees: Array of invited user/guest identities (with details populated)\n - createdBy: Creator identity information (auto-populated from authenticated user)\n - application: null\n - device: null\n - user: User identity with @odata.type, id, displayName, tenantId\n - coOrganizers: Array of coorganizer identities (with displayName populated)\n - settings: Townhall settings\n - externalEventInformation: Empty array initially\n\n Important Notes:\n - Townhalls are always created in 'draft' status\n - Only delegated permissions supported (no application permissions)\n - Personal Microsoft accounts are NOT supported\n - endDateTime must be after startDateTime\n - isInviteOnly can ONLY be true if audience='organization'\n - CoOrganizers must exist in the system\n - Invited attendees can be users (must exist) or guests (validated by email)\n - Creator information is auto-populated from authenticated user\n\n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventsroot-post-townhalls",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "displayName": {
+ "type": "string",
+ "description": "The display name of the townhall (required, 1-500 characters)"
+ },
+ "description": {
+ "type": "object",
+ "description": "Description of the townhall (required)",
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "html"
+ ],
+ "description": "Content type: 'text' or 'html' (default: 'text')"
+ },
+ "content": {
+ "type": "string",
+ "description": "Description content"
+ }
+ },
+ "required": [
+ "contentType",
+ "content"
+ ]
+ },
+ "startDateTime": {
+ "type": "object",
+ "description": "Start date and time (required)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "ISO 8601 date-time string (e.g., '2024-03-30T10:00:00')"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Windows timezone name (e.g., 'Pacific Standard Time', 'UTC', 'Eastern Standard Time'). IMPORTANT: Only Windows timezone names are supported, NOT IANA timezones like 'America/New_York'."
+ }
+ },
+ "required": [
+ "dateTime",
+ "timeZone"
+ ]
+ },
+ "endDateTime": {
+ "type": "object",
+ "description": "End date and time (required, must be after startDateTime)",
+ "properties": {
+ "dateTime": {
+ "type": "string",
+ "description": "ISO 8601 date-time string (e.g., '2024-03-30T17:00:00')"
+ },
+ "timeZone": {
+ "type": "string",
+ "description": "Windows timezone name (e.g., 'Pacific Standard Time', 'UTC', 'Eastern Standard Time'). IMPORTANT: Only Windows timezone names are supported, NOT IANA timezones like 'America/New_York'."
+ }
+ },
+ "required": [
+ "dateTime",
+ "timeZone"
+ ]
+ },
+ "audience": {
+ "type": "string",
+ "enum": [
+ "everyone",
+ "organization",
+ "unknownFutureValue"
+ ],
+ "description": "Audience visibility (required). 'organization' = internal only, 'everyone' = public access. Note: isInviteOnly can ONLY be true if audience='organization'."
+ },
+ "isInviteOnly": {
+ "type": "boolean",
+ "description": "Whether townhall is invite-only (optional, default: false). CRITICAL: Can ONLY be true if audience='organization'. If true, only invitedAttendees can join.",
+ "default": false
+ },
+ "invitedAttendees": {
+ "type": "array",
+ "description": "Invited attendees for the townhall (optional). Provide user IDs for existing users (details auto-populated) OR email addresses for guest identities.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User ID (for existing users - other fields auto-populated) OR email address (for guests). System automatically detects type based on format."
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ "coOrganizers": {
+ "type": "array",
+ "description": "Coorganizers of the townhall (optional). Provide only user IDs - displayName and tenantId are automatically populated from the database.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "User ID of coorganizer (required). All other fields (displayName, tenantId) auto-populated from database."
+ }
+ },
+ "required": [
+ "id"
+ ]
+ }
+ },
+ "settings": {
+ "type": "object",
+ "description": "Townhall settings (optional)",
+ "properties": {
+ "isAttendeeEmailNotificationEnabled": {
+ "type": "boolean",
+ "description": "Enable attendee email notifications (default: false)"
+ }
+ }
+ }
+ },
+ "required": [
+ "displayName",
+ "description",
+ "startDateTime",
+ "endDateTime",
+ "audience"
+ ]
+ }
+ },
+ {
+ "name": "list_virtual_event_townhalls",
+ "description": "Get the list of all virtualEventTownhall objects created in a tenant.\n\n API Endpoint: GET /solutions/virtualEvents/townhalls\n\n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): NOT SUPPORTED\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: VirtualEvent.Read.All (least privileged, ONLY)\n\n CRITICAL: This endpoint ONLY supports application permissions. Delegated permissions are NOT supported.\n\n IMPORTANT - Application Permission Policy:\n To use application permission for this API, tenant administrators must create an\n application access policy and grant it to a user to authorize the app configured\n in the policy to get townhalls on behalf of that user.\n\n Optional Query Parameters:\n - _count: Include total count of items (boolean). Maps to $count query parameter.\n When true, response includes @odata.count field with total number of townhalls.\n\n Response Properties:\n - value: Array of virtualEventTownhall objects\n - @odata.count: Total count of townhalls (only if _count=true)\n\n Each townhall object in the array includes:\n - id: Unique identifier (format: guid@guid)\n - status: Townhall status (draft, published, canceled, unknownFutureValue)\n - displayName, description, startDateTime, endDateTime, audience\n - isInviteOnly: Whether townhall is invite-only\n - invitedAttendees: Array of invited user/guest identities\n - createdBy: Creator identity information\n - coOrganizers: Array of coorganizer identities\n - settings: Townhall settings\n - externalEventInformation: External event information (only for organizers/coorganizers)\n\n Important Notes:\n - ONLY application permissions supported (NO delegated permissions)\n - Requires VirtualEvent.Read.All application permission\n - Application access policy must be configured by tenant administrators\n - Returns townhalls from the authenticated organization only\n - Default limit of 100 townhalls\n - Use _count=true to get total count in response\n\n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventsroot-list-townhalls",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_count": {
+ "type": "boolean",
+ "description": "Include total count in response (@odata.count). Maps to $count query parameter. Set to true to include count, false or omit to exclude.",
+ "default": false
+ }
+ },
+ "required": []
+ }
+ },
+ {
+ "name": "cancel_virtual_event_townhall",
+ "description": "Cancel a virtualEventTownhall. A canceled town hall has its status set to canceled permanently.\n \n CRITICAL: Only the Organizer (creator) can cancel a townhall.\n Co-organizers CANNOT cancel.\n \n **Action:** Changes townhall status to 'canceled' permanently\n \n **Status Transitions:**\n - draft \u2192 canceled (allowed, returns 204 No Content)\n - published \u2192 canceled (allowed, returns 204 No Content)\n - canceled \u2192 canceled (idempotent, returns 200 OK with message)\n \n **Permissions Required:**\n - VirtualEvent.ReadWrite:delegated (only delegated, NOT application)\n \n **Response:** 204 No Content on success (no response body)\n \n **Authorization:**\n - ONLY the Organizer can cancel\n - Co-organizers are NOT allowed to cancel\n - Non-organizers will receive 403 Forbidden\n \n **Note:** You can still get a canceled town hall by using the Get virtualEventTownhall API.\n \n **API Endpoint:** POST /solutions/virtualEvents/townhalls/{townhallId}/cancel\n \n Permissions (EXACT from Microsoft Documentation):\n - Delegated (work or school account): VirtualEvent.ReadWrite (least privileged)\n - Delegated (personal Microsoft account): NOT SUPPORTED\n - Application: NOT SUPPORTED\n \n Request Parameters:\n - townhall_id (required): The unique identifier of the townhall (format: guid@guid)\n \n Response:\n - 204 No Content: Townhall successfully canceled\n - 200 OK: Townhall already canceled (idempotent)\n - 404 Not Found: Townhall doesn't exist\n - 403 Forbidden: User is not the organizer\n \n Important Notes:\n - No request body required\n - Only the organizer (creator) can cancel\n - Co-organizers cannot cancel (same restriction as publish)\n - Can cancel from any status (draft or published)\n - Idempotent: Canceling already canceled townhall returns 200 OK\n - Canceled townhalls remain accessible via GET API\n \n Reference: https://learn.microsoft.com/en-us/graph/api/virtualeventtownhall-cancel\n ",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "townhall_id": {
+ "type": "string",
+ "description": "Unique identifier of the townhall (format: guid@guid). Example: 'bce9a3ca-a310-48fa-baf3-1cedcd04bb3f@4aa05bcc-1cac-4a83-a9ae-0db84b88f4ba'"
+ }
+ },
+ "required": [
+ "townhall_id"
+ ]
+ }
+ },
+ {
+ "name": "list_teams_apps",
+ "description": "List Teams apps from the Microsoft Teams app catalog.\n\nAPI Endpoint: GET /appCatalogs/teamsApps\n\nThis tool lists all Teams apps available in the organization's app catalog. You can filter, select specific fields, and expand related properties using OData query parameters.\n\nReference: https://learn.microsoft.com/en-us/graph/api/appcatalogs-list-teamsapps\n\nCommon Use Cases:\n1. List all organization-specific apps: Use _filter=distributionMethod eq 'organization'\n2. Find app by ID: Use _filter=id eq '{app-id}'\n3. Find app by external ID (manifest ID): Use _filter=externalId eq '{manifest-id}'\n4. Get specific fields only: Use _select=id,displayName,distributionMethod\n\nRequired Permissions:\n- AppCatalog.Read.All (least privileged)\n- AppCatalog.ReadWrite.All\n- Directory.Read.All",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "_filter": {
+ "type": "string",
+ "description": "OData filter to apply. Examples: \"distributionMethod eq 'organization'\", \"id eq 'b1c5353a-7aca-41b3-830f-27d5218fe0e5'\", \"externalId eq 'cf1ba4c7-f94e-4d80-ba90-5594b641a8ee'\""
+ },
+ "_select": {
+ "type": "string",
+ "description": "Comma-separated list of properties to return. Example: \"id,displayName,distributionMethod\""
+ },
+ "_expand": {
+ "type": "string",
+ "description": "Comma-separated list of relationships to expand. Example: \"appDefinitions\""
+ }
+ },
+ "required": []
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/export_eval_telemetry.py b/resources_servers/enterpriseops_gym/export_eval_telemetry.py
new file mode 100644
index 0000000000..2c967f13fa
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/export_eval_telemetry.py
@@ -0,0 +1,181 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Export rollouts to the eval team's per-turn telemetry schema (one JSONL row per turn).
+
+Input rollouts must be collected with ``responses_api_agents/turn_logging_agent`` (rows
+carry per-turn ``turns`` records with token usage, cached-token counts, timestamps, and
+tool-call names) against the ``enterpriseops_gym`` resources server (rows carry
+``tool_latencies_ms``).
+
+Field notes:
+- ``stacked_input`` equals ``input_length``: this harness's ReAct loop grows context
+ monotonically (no compaction/summarization), so each turn's prompt IS the full stack.
+- ``tokensBefore``/``tokensAfter``/``content before/after compaction`` are emitted as
+ null for the same reason — no compaction event ever occurs. Flagged for the eval team.
+- ``per-tool latency`` is emitted as this turn's total tool-execution milliseconds (int),
+ with per-call detail in the supplementary ``tool_latency_detail`` field. Latencies are
+ measured by the resources server's MCP proxy; model-side malformed tool calls never
+ reach it and align to null.
+- ``output_length`` includes reasoning tokens (API completion-token accounting), and
+ ``answer`` includes any reasoning-item summary text present in the turn's output slice.
+"""
+
+import argparse
+import json
+from pathlib import Path
+from typing import Any, Dict, List, Optional
+
+
+def render_question(responses_create_params: Dict[str, Any]) -> str:
+ """Render the task prompt (system + user messages) as readable text."""
+ parts = []
+ for message in responses_create_params.get("input") or []:
+ role = message.get("role", "user")
+ content = message.get("content", "")
+ if not isinstance(content, str):
+ content = json.dumps(content)
+ parts.append(f"[{role}]\n{content}")
+ return "\n\n".join(parts)
+
+
+def extract_turn_answer(turn: Dict[str, Any], output_items: List[Dict[str, Any]]) -> str:
+ """Assistant text for the turn, prefixed with any reasoning summaries in its slice."""
+ start, end = turn.get("output_start_index"), turn.get("output_end_index")
+ reasoning_texts: List[str] = []
+ if start is not None and end is not None:
+ for item in output_items[start:end]:
+ if item.get("type") == "reasoning":
+ for summary in item.get("summary") or []:
+ text = summary.get("text") if isinstance(summary, dict) else None
+ if text:
+ reasoning_texts.append(text)
+ answer = turn.get("assistant_text") or ""
+ if reasoning_texts:
+ answer = "\n".join(reasoning_texts) + ("\n\n" + answer if answer else "")
+ return answer
+
+
+def align_tool_latencies(
+ turns: List[Dict[str, Any]], tool_latencies: List[Dict[str, Any]]
+) -> List[List[Optional[Dict[str, Any]]]]:
+ """Align session-ordered tool latencies to turns by walking both in execution order.
+
+ A tool call whose arguments failed to parse never reaches the resources server, so it
+ has no latency record — those align to None rather than shifting later turns.
+ """
+ aligned: List[List[Optional[Dict[str, Any]]]] = []
+ pointer = 0
+ for turn in turns:
+ turn_latencies: List[Optional[Dict[str, Any]]] = []
+ for tool_name in turn.get("tool_call_names") or []:
+ if pointer < len(tool_latencies) and tool_latencies[pointer].get("tool") == tool_name:
+ turn_latencies.append(tool_latencies[pointer])
+ pointer += 1
+ else:
+ turn_latencies.append(None)
+ aligned.append(turn_latencies)
+ return aligned
+
+
+def export_rows(rollout_rows: List[Dict[str, Any]], total_passes: Optional[int] = None) -> List[Dict[str, Any]]:
+ # Passes per task (for trial_name) default to the observed repeat count.
+ passes_by_task: Dict[Any, int] = {}
+ for row in rollout_rows:
+ task_index = row.get("_ng_task_index")
+ passes_by_task[task_index] = passes_by_task.get(task_index, 0) + 1
+
+ telemetry_rows: List[Dict[str, Any]] = []
+ for row in rollout_rows:
+ turns = row.get("turns")
+ if turns is None:
+ raise ValueError(
+ "Rollout row has no per-turn 'turns' records. Collect rollouts with "
+ "responses_api_agents/turn_logging_agent (see enterpriseops_gym_turnlog.yaml)."
+ )
+
+ metadata = row.get("verifier_metadata") or {}
+ task_id = metadata.get("task_id", f"task_{row.get('_ng_task_index')}")
+ rollout_index = row.get("_ng_rollout_index", 0)
+ num_passes = total_passes or passes_by_task.get(row.get("_ng_task_index"), 1)
+ trial_name = f"{task_id}.{rollout_index + 1}-of-{num_passes}.default"
+
+ question = render_question(row.get("responses_create_params") or {})
+ output_items = (row.get("response") or {}).get("output") or []
+ is_resolved = row.get("reward", 0.0) == 1.0
+ latency_per_turn = align_tool_latencies(turns, row.get("tool_latencies_ms") or [])
+
+ for i, turn in enumerate(turns):
+ is_final_turn = i == len(turns) - 1
+ input_length = turn.get("input_tokens", 0)
+ cached = turn.get("cached_input_tokens", 0)
+ turn_latencies = latency_per_turn[i]
+ known_latencies = [entry["latency_ms"] for entry in turn_latencies if entry]
+
+ telemetry_rows.append(
+ {
+ "task_id": task_id,
+ "trial_name": trial_name,
+ "turn": turn.get("turn", i),
+ "num_turns": len(turns),
+ "input_length": input_length,
+ "output_length": turn.get("output_tokens", 0),
+ "stacked_input": input_length, # no compaction: prompt == full stack
+ "is_resolved": is_resolved,
+ "task_complete": bool(
+ is_final_turn and not turn.get("tool_call_names") and turn.get("assistant_text")
+ ),
+ "num_steps": turn.get("num_tool_calls", 0),
+ "timestamp": turn.get("timestamp"),
+ "question": question,
+ "answer": extract_turn_answer(turn, output_items),
+ "cached input length": cached,
+ "new input length": input_length - cached,
+ "tool_call names": ",".join(turn.get("tool_call_names") or []),
+ "per-tool latency": int(sum(known_latencies)) if known_latencies else None,
+ "tokensBefore": None, # no compaction in this harness
+ "tokensAfter": None,
+ "content before compaction": None,
+ "content after compaction": None,
+ # Supplementary (beyond the required schema)
+ "tool_latency_detail": turn_latencies,
+ "model": turn.get("model"),
+ "turn_duration_ms": turn.get("duration_ms"),
+ "domain": metadata.get("domain"),
+ "mode": metadata.get("mode"),
+ "reward": row.get("reward"),
+ }
+ )
+ return telemetry_rows
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--input", required=True, type=Path, help="Rollouts JSONL from the turn_logging_agent")
+ parser.add_argument("--output", required=True, type=Path)
+ parser.add_argument("--total-passes", type=int, default=None, help="Override {total_passes} in trial_name")
+ args = parser.parse_args()
+
+ rollout_rows = [json.loads(line) for line in open(args.input)]
+ telemetry_rows = export_rows(rollout_rows, total_passes=args.total_passes)
+
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with open(args.output, "w") as f:
+ for row in telemetry_rows:
+ f.write(json.dumps(row) + "\n")
+ print(f"Wrote {len(telemetry_rows)} turn rows ({len(rollout_rows)} trials) to {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/resources_servers/enterpriseops_gym/mcp_client.py b/resources_servers/enterpriseops_gym/mcp_client.py
new file mode 100644
index 0000000000..c38ea4dab0
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/mcp_client.py
@@ -0,0 +1,331 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Async MCP client for the EnterpriseOps-Gym MCP servers.
+
+A functional port of EnterpriseOps-Gym's ``benchmark/mcp_client.py`` with the transport
+swapped from per-request ``httpx.AsyncClient`` instances to NeMo Gym's pooled global
+aiohttp client (``nemo_gym.server_utils.request``), and all per-call state (database_id,
+context) passed per call instead of mutated on the client — the original mutates
+``client.database_id``, which is racy under concurrent rollouts.
+
+Return shapes intentionally mirror the EOG client 1:1 ({"success": ..., "result": ...,
+"error": ...}) so the verifier engine port stays line-for-line comparable.
+
+Why not the official MCP Python SDK (a core Gym dependency since #1682)? Evaluated and
+rejected 2026-07-08: (1) the SDK's streamable-HTTP client rides on httpx, which this repo
+bans for high-concurrency async paths — we'd need an aiohttp transport adapter anyway;
+(2) it binds headers at session level, but per-rollout isolation here requires PER-CALL
+``x-database-id``/context headers on a shared client (a session per rollout would
+reintroduce the per-task handshake overhead this port removed); (3) roughly half of this
+module talks to the gyms' NON-MCP REST endpoints (/api/seed-database, /api/delete-database,
+/api/sql-runner) which no MCP client covers; (4) the upstream gym containers are frozen at
+protocolVersion 2024-11-05, so SDK protocol-evolution tracking buys nothing. Note #1682's
+``MCPResourcesServer`` solves the INVERSE problem (exposing Gym-owned tools AS an MCP
+server to MCP-native agents) — see PARITY.md follow-ups for how that could let MCP-native
+agents like Claude Code run against these EnterpriseOps tools.
+"""
+
+import asyncio
+import json
+import logging
+import random
+import string
+import time
+from datetime import datetime
+from typing import Any, Dict, List, Optional
+
+from aiohttp import ClientTimeout
+
+from nemo_gym.server_utils import request
+
+
+logger = logging.getLogger(__name__)
+
+
+_SEED_SQL_CACHE: Dict[str, str] = {}
+
+
+def load_seed_sql(sql_file_path: str) -> str:
+ """Read a seed SQL file, caching contents in memory (files are reused across many rollouts)."""
+ cached = _SEED_SQL_CACHE.get(sql_file_path)
+ if cached is None:
+ with open(sql_file_path, "r", encoding="utf-8") as f:
+ cached = f.read()
+ _SEED_SQL_CACHE[sql_file_path] = cached
+ return cached
+
+
+def generate_database_id() -> str:
+ """Generate a unique database id, matching the EOG format (db__<9 alnum>)."""
+ timestamp = int(time.time() * 1000)
+ suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=9))
+ return f"db_{timestamp}_{suffix}"
+
+
+def context_to_headers(context: Optional[Dict[str, Any]]) -> Dict[str, str]:
+ """Convert EOG task context key-values to x-* headers (user_id -> x-user-id), as EOG does."""
+ headers: Dict[str, str] = {}
+ if context and isinstance(context, dict):
+ for key, value in context.items():
+ if not key.lower().startswith("x-"):
+ header_key = f"x-{key.lower().replace('_', '-')}"
+ else:
+ header_key = key
+ headers[header_key] = str(value)
+ return headers
+
+
+class MCPGymClient:
+ """JSON-RPC (streamable HTTP) MCP client for one EnterpriseOps gym server.
+
+ One instance per (gym server URL) — NOT per rollout. The MCP session handshake runs
+ once lazily; per-rollout isolation comes from the ``x-database-id`` header on each call.
+ """
+
+ def __init__(
+ self,
+ base_url: str,
+ auth_config: Optional[Dict[str, Any]] = None,
+ mcp_endpoint: str = "/mcp",
+ tool_call_timeout_seconds: float = 30.0,
+ sql_timeout_seconds: float = 30.0,
+ ) -> None:
+ self.base_url = base_url.rstrip("/")
+ self.mcp_endpoint = mcp_endpoint
+ self.auth_config = auth_config
+ self.tool_call_timeout_seconds = tool_call_timeout_seconds
+ self.sql_timeout_seconds = sql_timeout_seconds
+
+ self.mcp_session_id: Optional[str] = None
+ self._request_id = 1
+ self._initialize_lock = asyncio.Lock()
+
+ def _next_request_id(self) -> int:
+ self._request_id += 1
+ return self._request_id
+
+ def _get_auth_headers(self) -> Dict[str, str]:
+ """Get authentication headers for HTTP requests (verbatim EOG semantics)."""
+ if not self.auth_config:
+ return {}
+
+ auth_type = self.auth_config.get("type")
+ token = self.auth_config.get("token")
+ header_name = self.auth_config.get("header_name", "Authorization")
+
+ if auth_type == "bearer":
+ return {header_name: f"Bearer {token}"}
+ elif auth_type == "api_key":
+ return {header_name: token}
+
+ return {}
+
+ async def _send_jsonrpc(
+ self,
+ method: str,
+ params: Optional[Dict[str, Any]] = None,
+ extra_headers: Optional[Dict[str, str]] = None,
+ is_notification: bool = False,
+ timeout_seconds: Optional[float] = None,
+ ) -> Dict[str, Any]:
+ """Send a JSON-RPC request (or notification) to the MCP endpoint."""
+ payload: Dict[str, Any] = {"jsonrpc": "2.0", "method": method, "params": params or {}}
+ if not is_notification:
+ payload["id"] = self._next_request_id()
+
+ headers = {"Accept": "application/json, text/event-stream"}
+ headers.update(self._get_auth_headers())
+ if self.mcp_session_id:
+ headers["mcp-session-id"] = self.mcp_session_id
+ if extra_headers:
+ headers.update(extra_headers)
+
+ try:
+ response = await request(
+ method="POST",
+ url=f"{self.base_url}{self.mcp_endpoint}",
+ json=payload,
+ headers=headers,
+ timeout=ClientTimeout(total=timeout_seconds or self.tool_call_timeout_seconds),
+ )
+ except Exception as e:
+ logger.error(f"MCP request exception: {e}")
+ return {"success": False, "error": str(e)}
+
+ # Capture session ID from response headers
+ if "mcp-session-id" in response.headers:
+ self.mcp_session_id = response.headers["mcp-session-id"]
+
+ if is_notification:
+ return {"success": response.status in (200, 204), "status_code": response.status}
+
+ if response.status == 200:
+ data = json.loads(await response.read())
+ return {"success": True, "data": data}
+
+ error_msg = f"MCP request failed: {response.status} - {(await response.read()).decode(errors='replace')}"
+ logger.error(error_msg)
+ return {"success": False, "error": error_msg}
+
+ async def ensure_initialized(self) -> None:
+ """Run the MCP initialize handshake once per client (concurrency-safe)."""
+ if self.mcp_session_id is not None:
+ return
+ async with self._initialize_lock:
+ if self.mcp_session_id is not None:
+ return
+ params = {
+ "protocolVersion": "2024-11-05",
+ "capabilities": {"tools": {}},
+ "clientInfo": {"name": "nemo-gym-enterpriseops", "version": "1.0.0"},
+ }
+ result = await self._send_jsonrpc("initialize", params)
+ if not result.get("success"):
+ raise RuntimeError(f"Failed to initialize MCP session with {self.base_url}: {result.get('error')}")
+ await self._send_jsonrpc("notifications/initialized", {}, is_notification=True)
+ # Some servers do not set an mcp-session-id header. Use a sentinel so we don't re-initialize.
+ if self.mcp_session_id is None:
+ self.mcp_session_id = ""
+
+ async def list_tools(self) -> List[Dict[str, Any]]:
+ """List all available tools (raw MCP tool dicts with inputSchema)."""
+ await self.ensure_initialized()
+ result = await self._send_jsonrpc("tools/list", {})
+ if result.get("success"):
+ return result.get("data", {}).get("result", {}).get("tools", [])
+ return []
+
+ async def call_tool(
+ self,
+ tool_name: str,
+ arguments: Optional[Dict[str, Any]] = None,
+ database_id: Optional[str] = None,
+ context: Optional[Dict[str, Any]] = None,
+ ) -> Dict[str, Any]:
+ """Call a tool against a specific database. Mirrors the EOG return shape."""
+ await self.ensure_initialized()
+
+ extra_headers: Dict[str, str] = {}
+ if database_id:
+ extra_headers["x-database-id"] = database_id
+ extra_headers.update(context_to_headers(context))
+
+ params = {"name": tool_name, "arguments": arguments or {}}
+ result = await self._send_jsonrpc("tools/call", params, extra_headers=extra_headers)
+ if result.get("success"):
+ data = result.get("data", {})
+ return {"success": True, "result": data.get("result"), "error": data.get("error")}
+ return result
+
+ async def run_sql(
+ self,
+ query: str,
+ database_id: str,
+ context: Optional[Dict[str, Any]] = None,
+ ) -> Dict[str, Any]:
+ """Execute a SQL query via the gym's /api/sql-runner endpoint (EOG verifier transport)."""
+ headers = {"x-database-id": database_id}
+ headers.update(self._get_auth_headers())
+ headers.update(context_to_headers(context))
+
+ try:
+ response = await request(
+ method="POST",
+ url=f"{self.base_url}/api/sql-runner",
+ json={"query": query, "database_id": database_id},
+ headers=headers,
+ timeout=ClientTimeout(total=self.sql_timeout_seconds),
+ )
+ except Exception as e:
+ logger.error(f"SQL query execution failed: {e}")
+ return {"success": False, "error": str(e)}
+
+ if response.status == 200:
+ return {"success": True, "result": json.loads(await response.read())}
+
+ # Mirror EOG's HTTP error detail extraction
+ response_text = (await response.read()).decode(errors="replace")
+ try:
+ error_json = json.loads(response_text)
+ if isinstance(error_json, dict):
+ error_details = error_json.get("detail", error_json.get("message", response_text))
+ else:
+ error_details = response_text
+ except json.JSONDecodeError:
+ error_details = response_text
+
+ logger.error(f"HTTP error calling sql-runner API: {response.status} - {error_details}")
+ return {"success": False, "error": f"SQL API call failed (HTTP {response.status}): {error_details}"}
+
+ async def seed_database(self, sql_content: str, seed_semaphore: Optional[asyncio.Semaphore] = None) -> str:
+ """Create a new database from SQL content and return its database_id.
+
+ Timeout formula matches EOG: max(1200, 120 + len(sql)/102400) seconds.
+ """
+ database_id = generate_database_id()
+ db_name = f"Auto DB {datetime.now().strftime('%Y%m%d_%H%M%S')}"
+ payload = {
+ "database_id": database_id,
+ "name": db_name,
+ "description": "Auto-created by nemo-gym enterpriseops_gym resources server",
+ "sql_content": sql_content,
+ }
+ timeout_seconds = max(1200, int(120 + len(sql_content) / 102400))
+
+ async def _do_seed() -> None:
+ response = await request(
+ method="POST",
+ url=f"{self.base_url}/api/seed-database",
+ json=payload,
+ headers=self._get_auth_headers(),
+ timeout=ClientTimeout(total=timeout_seconds),
+ )
+ if response.status != 200:
+ body = (await response.read()).decode(errors="replace")
+ raise RuntimeError(f"Failed to seed database on {self.base_url} (HTTP {response.status}): {body}")
+
+ if seed_semaphore is not None:
+ async with seed_semaphore:
+ await _do_seed()
+ else:
+ await _do_seed()
+
+ logger.info(f"Seeded database {database_id} on {self.base_url}")
+ return database_id
+
+ async def delete_database(self, database_id: str) -> bool:
+ """Delete a database. Tolerates servers without a delete API (404/405), as EOG does."""
+ try:
+ response = await request(
+ method="DELETE",
+ url=f"{self.base_url}/api/delete-database",
+ json={"database_id": database_id},
+ headers=self._get_auth_headers(),
+ timeout=ClientTimeout(total=30),
+ )
+ except Exception as e:
+ logger.error(f"Error deleting database {database_id}: {e}")
+ return False
+
+ if response.status in (404, 405):
+ logger.warning(f"Server {self.base_url} does not support database deletion (HTTP {response.status})")
+ return False
+ if response.status != 200:
+ body = (await response.read()).decode(errors="replace")
+ logger.error(f"Error deleting database {database_id} (HTTP {response.status}): {body}")
+ return False
+
+ logger.info(f"Deleted database {database_id} on {self.base_url}")
+ return True
diff --git a/resources_servers/enterpriseops_gym/requirements.txt b/resources_servers/enterpriseops_gym/requirements.txt
new file mode 100644
index 0000000000..00ed83213e
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/requirements.txt
@@ -0,0 +1 @@
+-e nemo-gym[dev] @ ../../
diff --git a/resources_servers/enterpriseops_gym/schema_utils.py b/resources_servers/enterpriseops_gym/schema_utils.py
new file mode 100644
index 0000000000..d042730097
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/schema_utils.py
@@ -0,0 +1,127 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tool JSON-schema cleaning, ported verbatim from EnterpriseOps-Gym.
+
+This is a line-for-line port of ``benchmark/llm_client.py::LLMClient._clean_json_schema``
+from https://github.com/ServiceNow/EnterpriseOps-Gym (Apache 2.0). Parity with the
+upstream benchmark requires identical cleaning semantics, so please do NOT "improve"
+this logic — fix bugs upstream first, then mirror them here.
+"""
+
+import logging
+from typing import Any, Dict, List
+
+
+logger = logging.getLogger(__name__)
+
+
+def clean_json_schema(schema: Dict[str, Any]) -> Dict[str, Any]:
+ """Clean a JSON schema to be compatible with LLM APIs (Anthropic, Vertex AI, etc.)
+
+ Removes oneOf, allOf, anyOf at top level and converts to simple object schema.
+ Also handles optional parameters with type arrays like ['STRING', 'NULL'].
+ """
+ if not isinstance(schema, dict):
+ return {"type": "object", "properties": {}, "required": []}
+
+ # If schema has oneOf/allOf/anyOf at top level, extract the first valid object schema
+ if "oneOf" in schema:
+ logger.debug("Schema has oneOf at top level, extracting first object schema")
+ for option in schema["oneOf"]:
+ if isinstance(option, dict) and option.get("type") == "object":
+ schema = option
+ break
+ else:
+ # No object schema found, return empty
+ return {"type": "object", "properties": {}, "required": []}
+
+ if "allOf" in schema:
+ logger.debug("Schema has allOf at top level, merging schemas")
+ merged_schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": []}
+ for sub_schema in schema["allOf"]:
+ if isinstance(sub_schema, dict):
+ if "properties" in sub_schema:
+ merged_schema["properties"].update(sub_schema["properties"])
+ if "required" in sub_schema:
+ merged_schema["required"].extend(sub_schema["required"])
+ schema = merged_schema
+
+ if "anyOf" in schema:
+ logger.debug("Schema has anyOf at top level, extracting first object schema")
+ for option in schema["anyOf"]:
+ if isinstance(option, dict) and option.get("type") == "object":
+ schema = option
+ break
+ else:
+ return {"type": "object", "properties": {}, "required": []}
+
+ # Ensure schema has required fields
+ if "type" not in schema:
+ schema["type"] = "object"
+
+ if schema["type"] == "object" and "properties" not in schema:
+ schema["properties"] = {}
+
+ # Clean property schemas recursively to handle optional parameters
+ # Vertex AI doesn't support type arrays like ['STRING', 'NULL']
+ if "properties" in schema:
+ cleaned_properties = {}
+ optional_properties: List[str] = [] # Track properties that should not be required
+
+ for prop_name, prop_schema in schema["properties"].items():
+ if isinstance(prop_schema, dict):
+ cleaned_prop = prop_schema.copy()
+
+ # Handle type arrays like ['STRING', 'NULL'] or ['string', 'null']
+ if "type" in cleaned_prop and isinstance(cleaned_prop["type"], list):
+ type_list = cleaned_prop["type"]
+ # Filter out 'null' or 'NULL' and take the first non-null type
+ non_null_types = [t for t in type_list if t.lower() != "null"]
+ if non_null_types:
+ cleaned_prop["type"] = non_null_types[0]
+ # If NULL was in the list, this is an optional parameter
+ if len(non_null_types) < len(type_list):
+ optional_properties.append(prop_name)
+ logger.debug(
+ f"Property '{prop_name}' has optional type {type_list}, "
+ f"converted to {non_null_types[0]}"
+ )
+ else:
+ # All types were null, default to string
+ cleaned_prop["type"] = "string"
+ optional_properties.append(prop_name)
+
+ # Recursively clean nested object schemas
+ if cleaned_prop.get("type") == "object" and "properties" in cleaned_prop:
+ cleaned_prop = clean_json_schema(cleaned_prop)
+
+ # Handle arrays with item schemas
+ if cleaned_prop.get("type") == "array" and "items" in cleaned_prop:
+ if isinstance(cleaned_prop["items"], dict):
+ cleaned_prop["items"] = clean_json_schema(cleaned_prop["items"])
+
+ cleaned_properties[prop_name] = cleaned_prop
+ else:
+ cleaned_properties[prop_name] = prop_schema
+
+ schema["properties"] = cleaned_properties
+
+ # Remove optional properties from the required array
+ if "required" in schema and optional_properties:
+ schema["required"] = [req for req in schema["required"] if req not in optional_properties]
+ if optional_properties:
+ logger.debug(f"Removed optional properties from required list: {optional_properties}")
+
+ return schema
diff --git a/resources_servers/enterpriseops_gym/snapshot_tools.py b/resources_servers/enterpriseops_gym/snapshot_tools.py
new file mode 100644
index 0000000000..41086bae5b
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/snapshot_tools.py
@@ -0,0 +1,71 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Snapshot the tools/list of a running EnterpriseOps MCP gym server to JSON.
+
+EOG task JSONs carry only tool *names* (selected_tools); the schemas live behind the live
+MCP servers. NeMo Gym dataset rows must carry full tool definitions, so we snapshot each
+domain's tools once and let the converter bake them into the dataset. This also removes the
+per-task tools/list discovery the upstream harness performs.
+
+Usage:
+ python resources_servers/enterpriseops_gym/snapshot_tools.py \
+ --gym-url http://localhost:8001 --gym-name sn-csm-server \
+ --output resources_servers/enterpriseops_gym/data/tools/csm.json
+"""
+
+import argparse
+import asyncio
+import json
+from datetime import datetime, timezone
+from pathlib import Path
+
+from resources_servers.enterpriseops_gym.mcp_client import MCPGymClient
+
+
+async def snapshot(gym_url: str, gym_name: str, mcp_endpoint: str, output: Path) -> int:
+ client = MCPGymClient(base_url=gym_url, mcp_endpoint=mcp_endpoint)
+ tools = await client.list_tools()
+ if not tools:
+ raise RuntimeError(f"No tools returned by {gym_url}{mcp_endpoint} — is the gym server running?")
+
+ output.parent.mkdir(parents=True, exist_ok=True)
+ with open(output, "w") as f:
+ json.dump(
+ {
+ "gym_name": gym_name,
+ "gym_url": gym_url,
+ "snapshot_at": datetime.now(timezone.utc).isoformat(),
+ "tools": tools,
+ },
+ f,
+ indent=2,
+ )
+ print(f"Wrote {len(tools)} tools for gym '{gym_name}' to {output}")
+ return len(tools)
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--gym-url", required=True, help="Base URL of the running MCP gym server")
+ parser.add_argument("--gym-name", required=True, help="EOG gym server name (e.g. sn-csm-server)")
+ parser.add_argument("--mcp-endpoint", default="/mcp")
+ parser.add_argument("--output", required=True, type=Path)
+ args = parser.parse_args()
+
+ asyncio.run(snapshot(args.gym_url, args.gym_name, args.mcp_endpoint, args.output))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/resources_servers/enterpriseops_gym/tests/conftest.py b/resources_servers/enterpriseops_gym/tests/conftest.py
new file mode 100644
index 0000000000..01d9af9396
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/conftest.py
@@ -0,0 +1,123 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import asyncio
+import socket
+import threading
+import time
+from os import environ
+from pathlib import Path
+from typing import Callable
+from unittest.mock import MagicMock
+
+import pytest
+import uvicorn
+
+from nemo_gym.global_config import NEMO_GYM_CONFIG_DICT_ENV_VAR_NAME
+
+
+# The server's outbound MCP calls lazily build the global aiohttp client, which reads the
+# global config. Outside ng_run there is no head server and Hydra would try to parse
+# pytest's argv (and SystemExit) — pre-seed the documented child-process env var instead.
+environ.setdefault(NEMO_GYM_CONFIG_DICT_ENV_VAR_NAME, "{}")
+
+import nemo_gym.server_utils as server_utils # noqa: E402
+from nemo_gym.server_utils import ServerClient
+from resources_servers.enterpriseops_gym.app import (
+ EnterpriseOpsGymResourcesServer,
+ EnterpriseOpsGymResourcesServerConfig,
+)
+from resources_servers.enterpriseops_gym.tests.stub_gym import StubGymState, create_stub_gym_app
+
+
+FIXTURES_DIR = Path(__file__).parent / "fixtures"
+
+
+@pytest.fixture(autouse=True)
+def reset_global_aiohttp_client():
+ """The pooled aiohttp session binds to the first event loop that uses it; TestClient
+ creates a fresh loop per test, so drop the session between tests (same close pattern
+ as nemo_gym.server_utils.global_aiohttp_client_exit)."""
+ yield
+ client = server_utils._GLOBAL_AIOHTTP_CLIENT
+ if client is not None:
+ try:
+ asyncio.run(client.close())
+ except Exception:
+ pass
+ server_utils._GLOBAL_AIOHTTP_CLIENT = None
+
+
+def start_stub_gym():
+ """Start a stub gym server (uvicorn in a daemon thread). Returns (url, state, stop_fn)."""
+ state = StubGymState()
+ app = create_stub_gym_app(state)
+
+ sock = socket.socket()
+ sock.bind(("127.0.0.1", 0))
+ port = sock.getsockname()[1]
+ sock.close()
+
+ server = uvicorn.Server(uvicorn.Config(app, host="127.0.0.1", port=port, log_level="warning"))
+ thread = threading.Thread(target=server.run, daemon=True)
+ thread.start()
+
+ deadline = time.time() + 15
+ while not server.started:
+ if time.time() > deadline:
+ raise RuntimeError("Stub gym server failed to start")
+ time.sleep(0.05)
+
+ def stop() -> None:
+ server.should_exit = True
+ thread.join(timeout=5)
+
+ return f"http://127.0.0.1:{port}", state, stop
+
+
+@pytest.fixture(scope="session")
+def stub_gym():
+ """A real HTTP stub gym server the resources server can call."""
+ url, state, stop = start_stub_gym()
+ yield url, state
+ stop()
+
+
+@pytest.fixture
+def gym_env(stub_gym):
+ """Per-test view of the stub gym with clean state."""
+ url, state = stub_gym
+ state.reset()
+ return url, state
+
+
+@pytest.fixture
+def make_server() -> Callable[..., EnterpriseOpsGymResourcesServer]:
+ def _make(**config_overrides) -> EnterpriseOpsGymResourcesServer:
+ config = EnterpriseOpsGymResourcesServerConfig(
+ **(
+ dict(
+ host="0.0.0.0",
+ port=8080,
+ entrypoint="",
+ name="enterpriseops_gym",
+ seed_sql_root=str(FIXTURES_DIR),
+ janitor_interval_seconds=0, # tests drive cleanup_expired_sessions directly
+ )
+ | config_overrides
+ )
+ )
+ return EnterpriseOpsGymResourcesServer(config=config, server_client=MagicMock(spec=ServerClient))
+
+ return _make
diff --git a/resources_servers/enterpriseops_gym/tests/fixtures/seed_entitlement.sql b/resources_servers/enterpriseops_gym/tests/fixtures/seed_entitlement.sql
new file mode 100644
index 0000000000..937d96600b
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/fixtures/seed_entitlement.sql
@@ -0,0 +1,9 @@
+CREATE TABLE entitlement (
+ entitlement_id INTEGER PRIMARY KEY,
+ account_name TEXT,
+ coverage_hours TEXT,
+ max_cases_per_month INTEGER
+);
+
+INSERT INTO entitlement (entitlement_id, account_name, coverage_hours, max_cases_per_month)
+VALUES (73, 'Stark Industries', 'h8x5', 10);
diff --git a/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_cases.json b/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_cases.json
new file mode 100644
index 0000000000..499edceb81
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_cases.json
@@ -0,0 +1,39 @@
+{
+ "extraction": [
+ {"success": true, "result": {"data": [{"coverage_hours": "h24x7"}]}},
+ {"success": true, "result": {"data": [{"a": 1, "b": 2}]}},
+ {"success": true, "result": {"data": [{"a": 1}, {"a": 2}]}},
+ {"success": true, "result": {"data": []}},
+ {"success": true, "result": {"data": [{"COUNT(*)": 0}]}},
+ {"success": true, "result": {"rows": [{"c": 5}]}},
+ {"success": true, "result": {"rows": [[7]]}},
+ {"success": true, "result": {"rows": [[1, 2]]}},
+ {"success": true, "result": {"rows": [{"a": 1}, {"a": 2}]}},
+ {"success": true, "result": {"rows": []}},
+ {"success": true, "result": {"content": [{"type": "text", "text": "oops"}]}},
+ {"success": true, "result": {"content": "plain"}},
+ {"success": true, "result": {"result": 42}},
+ {"success": true, "result": {"other": 1}},
+ {"success": true, "result": "scalar-string"},
+ {"success": true, "result": {}},
+ {"success": false, "result": {"content": [{"type": "text", "text": "err"}]}},
+ {"success": false},
+ {}
+ ],
+ "comparison": [
+ {"actual": 0, "expected": "0", "comparison_type": "equals"},
+ {"actual": 0, "expected": 0, "comparison_type": "equals"},
+ {"actual": "h24x7", "expected": "h24x7", "comparison_type": "equals"},
+ {"actual": 1, "expected": "1", "comparison_type": "equals"},
+ {"actual": null, "expected": null, "comparison_type": "equals"},
+ {"actual": null, "expected": 0, "comparison_type": "equals"},
+ {"actual": 5, "expected": 3, "comparison_type": "greater_than"},
+ {"actual": "5", "expected": 3, "comparison_type": "greater_than"},
+ {"actual": 2, "expected": 3, "comparison_type": "less_than"},
+ {"actual": "hello world", "expected": "world", "comparison_type": "contains"},
+ {"actual": [1, 2], "expected": 1, "comparison_type": "contains"},
+ {"actual": [1, 2], "expected": "1", "comparison_type": "contains"},
+ {"actual": 5, "expected": 5, "comparison_type": "approximately"},
+ {"actual": {"a": 1}, "expected": {"a": 1}, "comparison_type": "equals"}
+ ]
+}
diff --git a/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_golden.json b/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_golden.json
new file mode 100644
index 0000000000..864bd36ef4
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/fixtures/verifier_parity_golden.json
@@ -0,0 +1,103 @@
+{
+ "extraction": [
+ "h24x7",
+ {
+ "a": 1,
+ "b": 2
+ },
+ [
+ {
+ "a": 1
+ },
+ {
+ "a": 2
+ }
+ ],
+ [],
+ 0,
+ 5,
+ 7,
+ [
+ 1,
+ 2
+ ],
+ [
+ {
+ "a": 1
+ },
+ {
+ "a": 2
+ }
+ ],
+ [],
+ "oops",
+ "plain",
+ 42,
+ {
+ "other": 1
+ },
+ "scalar-string",
+ {},
+ "err",
+ null,
+ null
+ ],
+ "comparison": [
+ {
+ "passed": false,
+ "details": "Comparison equals: 0 vs 0"
+ },
+ {
+ "passed": true,
+ "details": "Comparison equals: 0 vs 0"
+ },
+ {
+ "passed": true,
+ "details": "Comparison equals: h24x7 vs h24x7"
+ },
+ {
+ "passed": false,
+ "details": "Comparison equals: 1 vs 1"
+ },
+ {
+ "passed": true,
+ "details": "Comparison equals: None vs None"
+ },
+ {
+ "passed": false,
+ "details": "Comparison equals: None vs 0"
+ },
+ {
+ "passed": true,
+ "details": "Comparison greater_than: 5 vs 3"
+ },
+ {
+ "passed": false,
+ "details": "Comparison error: '>' not supported between instances of 'str' and 'int'"
+ },
+ {
+ "passed": true,
+ "details": "Comparison less_than: 2 vs 3"
+ },
+ {
+ "passed": true,
+ "details": "Comparison contains: hello world vs world"
+ },
+ {
+ "passed": false,
+ "details": "Comparison error: 'in ' requires string as left operand, not int"
+ },
+ {
+ "passed": true,
+ "details": "Comparison contains: [1, 2] vs 1"
+ },
+ {
+ "passed": false,
+ "details": "Unknown comparison type: approximately"
+ },
+ {
+ "passed": true,
+ "details": "Comparison equals: {'a': 1} vs {'a': 1}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/resources_servers/enterpriseops_gym/tests/generate_parity_golden.py b/resources_servers/enterpriseops_gym/tests/generate_parity_golden.py
new file mode 100644
index 0000000000..226631f4a5
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/generate_parity_golden.py
@@ -0,0 +1,55 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Generate verifier parity goldens by running the fixture cases through the ORIGINAL
+EnterpriseOps-Gym engine. Run this inside the EOG checkout with its venv, e.g.:
+
+ cd /path/to/enterpriseops-gym
+ .venv/bin/python /path/to/gym/resources_servers/enterpriseops_gym/tests/generate_parity_golden.py
+
+It imports ``benchmark.verifier.VerifierEngine`` from the EOG repo (must be on sys.path /
+be the CWD) and writes fixtures/verifier_parity_golden.json next to this script.
+"""
+
+import json
+from pathlib import Path
+from unittest.mock import MagicMock
+
+
+FIXTURES_DIR = Path(__file__).parent / "fixtures"
+
+
+def main() -> None:
+ from benchmark.verifier import VerifierEngine # the ORIGINAL EOG engine
+
+ engine = VerifierEngine(MagicMock(), MagicMock())
+
+ cases = json.loads((FIXTURES_DIR / "verifier_parity_cases.json").read_text())
+
+ golden = {
+ "extraction": [engine._extract_value_from_sql_result(case) for case in cases["extraction"]],
+ "comparison": [
+ engine._compare_values(case["actual"], case["expected"], case["comparison_type"])
+ for case in cases["comparison"]
+ ],
+ }
+
+ output_path = FIXTURES_DIR / "verifier_parity_golden.json"
+ output_path.write_text(json.dumps(golden, indent=2))
+ print(f"Wrote goldens for {len(golden['extraction'])} extraction and {len(golden['comparison'])} comparison cases")
+ print(f"-> {output_path}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/resources_servers/enterpriseops_gym/tests/stub_gym.py b/resources_servers/enterpriseops_gym/tests/stub_gym.py
new file mode 100644
index 0000000000..2fa839fa8a
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/stub_gym.py
@@ -0,0 +1,212 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""In-process stub of an EnterpriseOps MCP gym server, backed by per-database sqlite.
+
+Implements the exact HTTP surface the resources server depends on — POST /mcp (JSON-RPC
+initialize / notifications / tools/list / tools/call), POST /api/seed-database,
+DELETE /api/delete-database, POST /api/sql-runner — so the whole seed -> tool -> verify
+flow is testable offline with genuine SQL state mutations.
+"""
+
+import json
+import sqlite3
+from typing import Any, Dict, List, Optional
+
+from fastapi import FastAPI, Request, Response
+
+
+STUB_TOOLS = [
+ {
+ "name": "update_entitlement",
+ "description": "Update an entitlement's coverage hours and/or monthly case limit.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {"type": "integer", "description": "Entitlement to update"},
+ "coverage_hours": {"type": ["string", "null"], "description": "e.g. h24x7"},
+ "max_cases_per_month": {"type": ["integer", "null"], "description": "0 = unlimited"},
+ },
+ "required": ["entitlement_id", "coverage_hours", "max_cases_per_month"],
+ },
+ },
+ {
+ "name": "get_entitlement",
+ "description": "Fetch an entitlement row.",
+ "inputSchema": {
+ "type": "object",
+ "properties": {"entitlement_id": {"type": "integer", "description": ""}},
+ "required": ["entitlement_id"],
+ },
+ },
+]
+
+
+class StubGymState:
+ """Shared, inspectable state: live sqlite databases and an event log for assertions."""
+
+ def __init__(self) -> None:
+ self.dbs: Dict[str, sqlite3.Connection] = {}
+ self.seed_events: List[str] = []
+ self.delete_events: List[str] = []
+ self.tool_calls: List[Dict[str, Any]] = []
+ self.sql_calls: List[Dict[str, Any]] = []
+
+ def reset(self) -> None:
+ for connection in self.dbs.values():
+ connection.close()
+ self.dbs.clear()
+ self.seed_events.clear()
+ self.delete_events.clear()
+ self.tool_calls.clear()
+ self.sql_calls.clear()
+
+
+def _rows_as_dicts(cursor: sqlite3.Cursor) -> List[Dict[str, Any]]:
+ columns = [d[0] for d in cursor.description] if cursor.description else []
+ return [dict(zip(columns, row)) for row in cursor.fetchall()]
+
+
+def _jsonrpc_tool_result(request_id: Any, text: str, is_error: bool = False) -> Dict[str, Any]:
+ return {
+ "jsonrpc": "2.0",
+ "id": request_id,
+ "result": {"content": [{"type": "text", "text": text}], "isError": is_error},
+ }
+
+
+def create_stub_gym_app(state: StubGymState) -> FastAPI:
+ app = FastAPI()
+
+ @app.post("/api/seed-database")
+ async def seed_database(request: Request) -> Dict[str, Any]:
+ payload = await request.json()
+ database_id = payload["database_id"]
+ connection = sqlite3.connect(":memory:", check_same_thread=False)
+ connection.executescript(payload["sql_content"])
+ connection.commit()
+ state.dbs[database_id] = connection
+ state.seed_events.append(database_id)
+ return {"status": "ok", "database_id": database_id}
+
+ @app.delete("/api/delete-database")
+ async def delete_database(request: Request) -> Dict[str, Any]:
+ payload = await request.json()
+ database_id = payload["database_id"]
+ connection = state.dbs.pop(database_id, None)
+ if connection is not None:
+ connection.close()
+ state.delete_events.append(database_id)
+ return {"status": "deleted", "database_id": database_id}
+
+ @app.post("/api/sql-runner")
+ async def sql_runner(request: Request) -> Response:
+ payload = await request.json()
+ database_id = payload.get("database_id") or request.headers.get("x-database-id")
+ state.sql_calls.append(
+ {"query": payload.get("query"), "database_id": database_id, "headers": dict(request.headers)}
+ )
+
+ connection = state.dbs.get(database_id)
+ if connection is None:
+ return Response(
+ content=json.dumps({"detail": f"Unknown database: {database_id}"}),
+ media_type="application/json",
+ status_code=404,
+ )
+ try:
+ cursor = connection.execute(payload["query"])
+ return Response(content=json.dumps({"data": _rows_as_dicts(cursor)}), media_type="application/json")
+ except sqlite3.Error as e:
+ return Response(
+ content=json.dumps({"detail": f"SQL error: {e}"}), media_type="application/json", status_code=400
+ )
+
+ def _call_tool(
+ name: str, arguments: Dict[str, Any], database_id: Optional[str], request_id: Any
+ ) -> Dict[str, Any]:
+ connection = state.dbs.get(database_id)
+ if connection is None:
+ return _jsonrpc_tool_result(request_id, f"Unknown database: {database_id}", is_error=True)
+
+ if name == "update_entitlement":
+ sets, params = [], []
+ for column in ("coverage_hours", "max_cases_per_month"):
+ if arguments.get(column) is not None:
+ sets.append(f"{column} = ?")
+ params.append(arguments[column])
+ if not sets:
+ return _jsonrpc_tool_result(request_id, "Nothing to update", is_error=True)
+ params.append(arguments["entitlement_id"])
+ connection.execute(f"UPDATE entitlement SET {', '.join(sets)} WHERE entitlement_id = ?", params)
+ connection.commit()
+ return _jsonrpc_tool_result(
+ request_id, json.dumps({"success": True, "entitlement_id": arguments["entitlement_id"]})
+ )
+
+ if name == "get_entitlement":
+ cursor = connection.execute(
+ "SELECT * FROM entitlement WHERE entitlement_id = ?", [arguments["entitlement_id"]]
+ )
+ rows = _rows_as_dicts(cursor)
+ return _jsonrpc_tool_result(request_id, json.dumps(rows[0] if rows else None))
+
+ return _jsonrpc_tool_result(request_id, f"Error: Tool '{name}' not found.", is_error=True)
+
+ @app.post("/mcp")
+ async def mcp(request: Request) -> Response:
+ payload = await request.json()
+ method = payload.get("method")
+ request_id = payload.get("id")
+
+ if method == "initialize":
+ body = {
+ "jsonrpc": "2.0",
+ "id": request_id,
+ "result": {
+ "protocolVersion": "2024-11-05",
+ "capabilities": {"tools": {}},
+ "serverInfo": {"name": "stub-gym", "version": "1.0.0"},
+ },
+ }
+ return Response(
+ content=json.dumps(body),
+ media_type="application/json",
+ headers={"mcp-session-id": "stub-mcp-session"},
+ )
+
+ if method == "notifications/initialized":
+ return Response(content=json.dumps({}), media_type="application/json")
+
+ if method == "tools/list":
+ body = {"jsonrpc": "2.0", "id": request_id, "result": {"tools": STUB_TOOLS}}
+ return Response(content=json.dumps(body), media_type="application/json")
+
+ if method == "tools/call":
+ params = payload.get("params") or {}
+ name = params.get("name")
+ arguments = params.get("arguments") or {}
+ database_id = request.headers.get("x-database-id")
+ state.tool_calls.append(
+ {"tool": name, "arguments": arguments, "database_id": database_id, "headers": dict(request.headers)}
+ )
+ return Response(
+ content=json.dumps(_call_tool(name, arguments, database_id, request_id)),
+ media_type="application/json",
+ )
+
+ body = {"jsonrpc": "2.0", "id": request_id, "error": {"code": -32601, "message": f"Unknown method {method}"}}
+ return Response(content=json.dumps(body), media_type="application/json")
+
+ return app
diff --git a/resources_servers/enterpriseops_gym/tests/test_app.py b/resources_servers/enterpriseops_gym/tests/test_app.py
new file mode 100644
index 0000000000..709efed89a
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/test_app.py
@@ -0,0 +1,450 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Offline end-to-end tests: seed -> tool call -> verify against the sqlite-backed stub gym."""
+
+import asyncio
+import contextlib
+import json
+import time
+from typing import Any, Dict, List, Optional
+
+from fastapi.testclient import TestClient
+from httpx import Cookies
+
+import nemo_gym.server_utils as server_utils
+
+
+GYM_NAME = "stub-gym"
+
+
+def make_verifier(
+ name: str,
+ query: str,
+ expected_value: Any,
+ comparison_type: str = "equals",
+ gym_name: Optional[str] = GYM_NAME,
+) -> Dict[str, Any]:
+ verifier = {
+ "verifier_type": "database_state",
+ "name": name,
+ "validation_config": {"query": query, "expected_value": expected_value, "comparison_type": comparison_type},
+ }
+ if gym_name is not None:
+ verifier["gym_name"] = gym_name
+ return verifier
+
+
+V_COVERAGE = make_verifier(
+ "update_entitlement", "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "h24x7"
+)
+V_MAX_CASES = make_verifier(
+ "update_entitlement", "SELECT max_cases_per_month FROM entitlement WHERE entitlement_id = 73;", 0
+)
+V_COUNT = make_verifier("update_entitlement", "SELECT COUNT(*) FROM entitlement WHERE entitlement_id = 73;", 1)
+
+
+def make_row(stub_url: str, verifiers: List[Dict[str, Any]]) -> Dict[str, Any]:
+ return {
+ "responses_create_params": {
+ "input": [
+ {"role": "system", "content": "You are a CSM administrator."},
+ {"role": "user", "content": "Upgrade entitlement 73 to 24x7 with unlimited cases."},
+ ],
+ "tools": [],
+ },
+ "verifier_metadata": {
+ "task_id": "test_task",
+ "domain": "csm",
+ "mode": "oracle",
+ "gym_servers_config": [
+ {
+ "mcp_server_name": GYM_NAME,
+ "mcp_server_url": stub_url,
+ "seed_database_file": "seed_entitlement.sql",
+ "context": {"x-user-email": "joanne@example.com"},
+ }
+ ],
+ "verifiers": verifiers,
+ "selected_tools": [],
+ "restricted_tools": [],
+ "tool_to_gym": {},
+ },
+ }
+
+
+def make_nemogym_response(output: List[Dict[str, Any]]) -> Dict[str, Any]:
+ return {
+ "id": "resp_test",
+ "created_at": 0,
+ "model": "test-model",
+ "object": "response",
+ "output": output,
+ "parallel_tool_calls": True,
+ "tool_choice": "auto",
+ "tools": [],
+ }
+
+
+FN_CALL_ITEM = {
+ "type": "function_call",
+ "id": "fc_1",
+ "call_id": "call_1",
+ "name": "update_entitlement",
+ "arguments": json.dumps({"entitlement_id": 73, "coverage_hours": "h24x7", "max_cases_per_month": 0}),
+ "status": "completed",
+}
+FINAL_MESSAGE_ITEM = {
+ "type": "message",
+ "id": "msg_1",
+ "role": "assistant",
+ "status": "completed",
+ "content": [{"type": "output_text", "text": "Entitlement 73 upgraded.", "annotations": []}],
+}
+
+
+def run_agent_flow(client: TestClient, row: Dict[str, Any], do_tool_call: bool = True) -> Dict[str, Any]:
+ """Drive the seed -> tool -> verify flow like simple_agent would (TestClient keeps cookies)."""
+ seed_response = client.post("/seed_session", json=row)
+ assert seed_response.status_code == 200, seed_response.text
+
+ if do_tool_call:
+ tool_response = client.post(
+ "/update_entitlement",
+ json={"entitlement_id": 73, "coverage_hours": "h24x7", "max_cases_per_month": 0},
+ )
+ assert tool_response.status_code == 200, tool_response.text
+
+ output = [FN_CALL_ITEM, FINAL_MESSAGE_ITEM] if do_tool_call else [FINAL_MESSAGE_ITEM]
+ verify_body = row | {"response": make_nemogym_response(output)}
+ verify_response = client.post("/verify", json=verify_body)
+ assert verify_response.status_code == 200, verify_response.text
+ return verify_response.json()
+
+
+class TestSeedToolVerify:
+ def test_success_flow_and_name_collapse_counts(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COVERAGE, V_MAX_CASES, V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ result = run_agent_flow(client, row)
+
+ assert result["reward"] == 1.0
+ assert result["overall_success"] is True
+ # All three verifiers share the name "update_entitlement" -> EOG collapses to 1 scored.
+ assert result["num_verifiers_defined"] == 3
+ assert result["num_verifiers_scored"] == 1
+ assert list(result["verification_results"].keys()) == ["update_entitlement"]
+ # Strict view still counts all three.
+ assert result["strict_success"] is True
+ assert result["strict_pass_rate"] == 1.0
+ assert result["num_tool_calls"] == 1
+ # Per-tool latency was recorded by the proxy and surfaced in the verify response.
+ assert len(result["tool_latencies_ms"]) == 1
+ assert result["tool_latencies_ms"][0]["tool"] == "update_entitlement"
+ assert result["tool_latencies_ms"][0]["gym"] == GYM_NAME
+ assert result["tool_latencies_ms"][0]["latency_ms"] > 0
+ # The rollout's database was seeded and deleted.
+ assert len(state.seed_events) == 1
+ assert state.delete_events == state.seed_events
+ assert state.dbs == {}
+
+ def test_name_collapse_masks_earlier_failure(self, gym_env, make_server) -> None:
+ """EOG parity quirk: only the LAST verifier per name is scored, so an earlier
+ same-named failure is masked. Strict scoring catches it."""
+ stub_url, state = gym_env
+ server = make_server()
+ failing_first = make_verifier(
+ "update_entitlement", "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "WRONG_VALUE"
+ )
+ row = make_row(stub_url, [failing_first, V_COUNT]) # same name; V_COUNT passes and wins
+
+ with TestClient(server.setup_webserver()) as client:
+ # No tool call: coverage stays h8x5, so failing_first truly fails.
+ result = run_agent_flow(client, row, do_tool_call=False)
+
+ assert result["reward"] == 1.0 # EOG-parity: masked by the collapse
+ assert result["overall_success"] is True
+ assert result["num_verifiers_defined"] == 2
+ assert result["num_verifiers_scored"] == 1
+ assert result["strict_success"] is False
+ assert result["strict_pass_rate"] == 0.5
+
+ def test_strict_verifiers_mode_flips_reward(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server(strict_verifiers=True)
+ failing_first = make_verifier(
+ "update_entitlement", "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "WRONG_VALUE"
+ )
+ row = make_row(stub_url, [failing_first, V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ result = run_agent_flow(client, row, do_tool_call=False)
+
+ assert result["overall_success"] is True # parity metric unchanged
+ assert result["reward"] == 0.0 # but strict reward catches the masked failure
+
+ def test_empty_verifier_set_never_passes_strict(self, gym_env, make_server) -> None:
+ # A task defining zero verifiers (or only skipped ones) must not score as a strict/RL
+ # success via all([]) == True. The collapsed parity metric intentionally keeps the
+ # upstream all([]) behavior (PARITY.md §1).
+ stub_url, state = gym_env
+ server = make_server(strict_verifiers=True)
+ row = make_row(stub_url, [])
+
+ with TestClient(server.setup_webserver()) as client:
+ result = run_agent_flow(client, row, do_tool_call=False)
+
+ assert result["reward"] == 0.0 # strict mode: empty verifier set is not a success
+ assert result["strict_success"] is False
+ assert result["strict_pass_rate"] == 0.0
+ assert result["overall_success"] is True # parity-pinned upstream quirk
+ assert result["num_verifiers_defined"] == 0
+ assert result["num_verifiers_scored"] == 0
+
+ def test_distinct_name_failure_fails_task(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ distinct_fail = make_verifier(
+ "check_coverage", "SELECT coverage_hours FROM entitlement WHERE entitlement_id = 73;", "h24x7"
+ )
+ row = make_row(stub_url, [distinct_fail, V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ result = run_agent_flow(client, row, do_tool_call=False) # no update -> h8x5 != h24x7
+
+ assert result["reward"] == 0.0
+ assert result["overall_success"] is False
+ assert result["num_verifiers_scored"] == 2
+ assert result["verifier_pass_rate"] == 0.5
+
+
+class TestToolProxy:
+ def test_tool_observation_and_headers(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ seed_response = client.post("/seed_session", json=row)
+ database_id = seed_response.json()["databases"][GYM_NAME]
+ assert database_id
+
+ tool_response = client.post("/update_entitlement", json={"entitlement_id": 73, "coverage_hours": "h24x7"})
+
+ # EOG parity: the body is json.dumps() — content list + isError.
+ observed = json.loads(tool_response.text)
+ assert observed["isError"] is False
+ assert observed["content"][0]["type"] == "text"
+ assert json.loads(observed["content"][0]["text"]) == {"success": True, "entitlement_id": 73}
+
+ # database id + task context headers were forwarded to the MCP server.
+ recorded = state.tool_calls[-1]
+ assert recorded["database_id"] == database_id
+ assert recorded["headers"].get("x-user-email") == "joanne@example.com"
+
+ def test_tool_call_without_session_is_400(self, gym_env, make_server) -> None:
+ stub_url, _ = gym_env
+ server = make_server()
+ with TestClient(server.setup_webserver()) as client:
+ response = client.post("/update_entitlement", json={"entitlement_id": 73})
+ assert response.status_code == 400
+ assert "seed_session" in response.json()["error"]
+
+ def test_sessions_are_isolated(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COUNT])
+
+ # One TestClient (one event loop) with cookie auto-persistence defeated, so we can
+ # drive two independent sessions by passing cookies explicitly — the same pattern
+ # as resources_servers/example_session_state_mgmt/tests/test_app.py.
+ with TestClient(server.setup_webserver()) as client:
+
+ class StatelessCookies(Cookies):
+ def extract_cookies(self, response):
+ pass
+
+ client._cookies = StatelessCookies(client._cookies)
+
+ response_a = client.post("/seed_session", json=row)
+ cookies_a = response_a.cookies
+ db_a = response_a.json()["databases"][GYM_NAME]
+
+ response_b = client.post("/seed_session", json=row)
+ cookies_b = response_b.cookies
+ db_b = response_b.json()["databases"][GYM_NAME]
+ assert db_a != db_b
+
+ # Mutate only session A's database.
+ client.post(
+ "/update_entitlement",
+ json={"entitlement_id": 73, "coverage_hours": "h24x7"},
+ cookies=cookies_a,
+ )
+
+ a_val = state.dbs[db_a].execute("SELECT coverage_hours FROM entitlement").fetchone()[0]
+ b_val = state.dbs[db_b].execute("SELECT coverage_hours FROM entitlement").fetchone()[0]
+ assert a_val == "h24x7"
+ assert b_val == "h8x5"
+ assert cookies_b is not None # both sessions were established
+
+
+class TestVerifyLifecycle:
+ def test_verify_is_idempotent_and_deletes_db_once(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COUNT])
+ verify_body = row | {"response": make_nemogym_response([FINAL_MESSAGE_ITEM])}
+
+ with TestClient(server.setup_webserver()) as client:
+ client.post("/seed_session", json=row)
+ first = client.post("/verify", json=verify_body).json()
+ second = client.post("/verify", json=verify_body).json()
+
+ assert first["reward"] == second["reward"] == 1.0
+ assert first["verification_results"] == second["verification_results"]
+ assert len(state.delete_events) == 1 # not deleted twice
+
+ def test_janitor_cleans_unverified_sessions(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ client.post("/seed_session", json=row)
+ assert len(state.seed_events) == 1
+ assert state.delete_events == []
+
+ # The TestClient's loop is gone; recycle the pooled aiohttp session for this loop.
+ if server_utils._GLOBAL_AIOHTTP_CLIENT is not None:
+ with contextlib.suppress(Exception):
+ asyncio.run(server_utils._GLOBAL_AIOHTTP_CLIENT.close())
+ server_utils._GLOBAL_AIOHTTP_CLIENT = None
+
+ num_removed = asyncio.run(server.cleanup_expired_sessions(now=time.time() + 100_000))
+
+ assert num_removed == 1
+ assert server.sessions == {}
+ assert state.delete_events == state.seed_events
+
+ def test_missing_seed_file_proceeds_with_no_database(self, gym_env, make_server) -> None:
+ """EOG parity: a missing seed SQL file logs an error and proceeds with database_id=None."""
+ stub_url, state = gym_env
+ server = make_server()
+ row = make_row(stub_url, [V_COUNT])
+ row["verifier_metadata"]["gym_servers_config"][0]["seed_database_file"] = "does_not_exist.sql"
+
+ with TestClient(server.setup_webserver()) as client:
+ seed_response = client.post("/seed_session", json=row)
+ assert seed_response.status_code == 200
+ assert seed_response.json()["databases"][GYM_NAME] is None
+
+ verify_body = row | {"response": make_nemogym_response([FINAL_MESSAGE_ITEM])}
+ result = client.post("/verify", json=verify_body).json()
+
+ # The SQL verifier fails against the unknown database, so the task fails.
+ assert result["reward"] == 0.0
+
+
+class TestReplicaPool:
+ def test_seed_sessions_round_robin_across_replicas(self, gym_env, make_server) -> None:
+ from resources_servers.enterpriseops_gym.tests.conftest import start_stub_gym
+
+ url_a, state_a = gym_env
+ url_b, state_b, stop_b = start_stub_gym()
+ try:
+ server = make_server(gym_url_pools={GYM_NAME: [url_a, url_b]})
+ row = make_row(url_a, [V_COUNT]) # dataset URL is ignored when a pool is configured
+
+ with TestClient(server.setup_webserver()) as client:
+
+ class StatelessCookies(Cookies):
+ def extract_cookies(self, response):
+ pass
+
+ client._cookies = StatelessCookies(client._cookies)
+
+ # Two fresh sessions -> replicas A then B.
+ client.post("/seed_session", json=row)
+ client.post("/seed_session", json=row)
+
+ assert len(state_a.seed_events) == 1
+ assert len(state_b.seed_events) == 1
+ pinned = sorted(gym.base_url for s in server.sessions.values() for gym in s.gyms.values())
+ assert pinned == sorted([url_a, url_b])
+ finally:
+ stop_b()
+
+
+class TestAggregateMetrics:
+ def test_compute_metrics_per_domain(self, make_server) -> None:
+ server = make_server()
+ tasks = [
+ [
+ {
+ "verifier_metadata": {"domain": "csm"},
+ "reward": 1.0,
+ "verifier_pass_rate": 1.0,
+ "strict_pass_rate": 1.0,
+ },
+ {
+ "verifier_metadata": {"domain": "csm"},
+ "reward": 0.0,
+ "verifier_pass_rate": 0.5,
+ "strict_pass_rate": 0.4,
+ },
+ ],
+ [
+ {
+ "verifier_metadata": {"domain": "teams"},
+ "reward": 0.0,
+ "verifier_pass_rate": 0.0,
+ "strict_pass_rate": 0.0,
+ },
+ ],
+ ]
+ metrics = server.compute_metrics(tasks)
+ assert metrics["csm/success_rate"] == 0.5
+ assert metrics["csm/verifier_pass_rate"] == 0.75
+ assert metrics["csm/num_rollouts"] == 2
+ assert metrics["teams/success_rate"] == 0.0
+ assert metrics["macro_success_rate"] == 0.25 # mean of per-domain success rates
+
+
+class TestVerifierKinds:
+ def test_tool_execution_verifier_and_skipped_gym(self, gym_env, make_server) -> None:
+ stub_url, state = gym_env
+ server = make_server()
+ tool_exec_verifier = {
+ "verifier_type": "tool_execution",
+ "name": "used_update",
+ "gym_name": GYM_NAME,
+ "validation_config": {"selected_tools": ["update_entitlement"], "minimum_tool_calls": 1},
+ }
+ unknown_gym_verifier = make_verifier("orphan", "SELECT 1;", 1, gym_name="nonexistent-gym")
+ row = make_row(stub_url, [tool_exec_verifier, unknown_gym_verifier, V_COUNT])
+
+ with TestClient(server.setup_webserver()) as client:
+ result = run_agent_flow(client, row)
+
+ # EOG parity: the unknown-gym verifier is skipped entirely (absent from results).
+ assert set(result["verification_results"].keys()) == {"used_update", "update_entitlement"}
+ assert result["reward"] == 1.0
+ assert result["num_verifiers_defined"] == 3
+ assert result["num_verifiers_scored"] == 2
+ # Strict counts the skipped verifier as failed.
+ assert result["strict_success"] is False
diff --git a/resources_servers/enterpriseops_gym/tests/test_convert_tasks.py b/resources_servers/enterpriseops_gym/tests/test_convert_tasks.py
new file mode 100644
index 0000000000..d19f18e099
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/test_convert_tasks.py
@@ -0,0 +1,184 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import json
+
+import pytest
+
+from resources_servers.enterpriseops_gym.convert_tasks import (
+ build_tools_for_task,
+ convert,
+ convert_task,
+ load_snapshots,
+ strip_private_keys,
+)
+
+
+SNAPSHOT = {
+ "gym_name": "sn-csm-server",
+ "gym_url": "http://localhost:8001",
+ "snapshot_at": "2026-07-07T00:00:00+00:00",
+ "tools": [
+ {
+ "name": "find_user",
+ "description": "Find a user",
+ "inputSchema": {
+ "type": "object",
+ "properties": {"name": {"type": "string", "description": ""}},
+ "required": ["name"],
+ },
+ },
+ {
+ "name": "update_entitlement",
+ "description": "Update an entitlement",
+ "inputSchema": {
+ "type": "object",
+ "properties": {
+ "entitlement_id": {"type": "integer", "description": ""},
+ "coverage_hours": {"type": ["string", "null"], "description": "optional"},
+ },
+ "required": ["entitlement_id", "coverage_hours"],
+ },
+ },
+ {
+ "name": "create_new_case",
+ "description": "Create a case",
+ "inputSchema": {"type": "object", "properties": {}, "required": []},
+ },
+ ],
+}
+
+TASK = {
+ "_comment": "should be stripped",
+ "system_prompt": "CSM Agent Policy ...",
+ "user_prompt": "Upgrade the entitlement.",
+ "mcp_endpoint": "/mcp",
+ "number_of_runs": 1,
+ "gym_servers_config": [
+ {
+ "mcp_server_name": "sn-csm-server",
+ "mcp_server_url": "http://localhost:8001",
+ "seed_database_file": "Domain Wise DBs and Task-DB Mappings/csm/dbs/db_x.sql",
+ "context": {"x-user-email": "joanne@example.com"},
+ }
+ ],
+ "selected_tools": ["update_entitlement", "find_user"],
+ "restricted_tools": ["find_user"],
+ "verifiers": [
+ {
+ "verifier_type": "database_state",
+ "name": "update_entitlement",
+ "_description": "should be stripped",
+ "gym_name": "sn-csm-server",
+ "validation_config": {"query": "SELECT 1;", "expected_value": 1, "comparison_type": "equals"},
+ }
+ ],
+}
+
+
+@pytest.fixture
+def snapshot_path(tmp_path):
+ path = tmp_path / "csm.json"
+ path.write_text(json.dumps(SNAPSHOT))
+ return path
+
+
+class TestConvertTask:
+ def test_full_conversion(self, snapshot_path) -> None:
+ gym_tools = load_snapshots([snapshot_path])
+ row = convert_task(dict(TASK), "task_1", "csm", "oracle", gym_tools)
+
+ # Messages
+ messages = row["responses_create_params"]["input"]
+ assert messages[0] == {"role": "system", "content": TASK["system_prompt"]}
+ assert messages[1] == {"role": "user", "content": TASK["user_prompt"]}
+
+ # selected minus restricted -> only update_entitlement
+ tools = row["responses_create_params"]["tools"]
+ assert [t["name"] for t in tools] == ["update_entitlement"]
+ assert tools[0]["type"] == "function"
+ assert tools[0]["strict"] is False # EOG parity: non-strict tool binding
+
+ # EOG schema cleaning: nullable type array collapsed and demoted from required
+ parameters = tools[0]["parameters"]
+ assert parameters["properties"]["coverage_hours"]["type"] == "string"
+ assert parameters["required"] == ["entitlement_id"]
+
+ # Metadata
+ metadata = row["verifier_metadata"]
+ assert metadata["task_id"] == "task_1"
+ assert metadata["domain"] == "csm"
+ assert metadata["mode"] == "oracle"
+ assert metadata["tool_to_gym"] == {"update_entitlement": "sn-csm-server"}
+ assert metadata["gym_servers_config"] == TASK["gym_servers_config"]
+ # Private keys stripped
+ assert "_description" not in metadata["verifiers"][0]
+
+ def test_empty_selected_tools_means_all_in_snapshot_order(self, snapshot_path) -> None:
+ gym_tools = load_snapshots([snapshot_path])
+ task = dict(TASK) | {"selected_tools": [], "restricted_tools": []}
+ tools, task_tool_to_gym = build_tools_for_task(task, gym_tools)
+ assert [t["name"] for t in tools] == ["find_user", "update_entitlement", "create_new_case"]
+ assert set(task_tool_to_gym.values()) == {"sn-csm-server"}
+
+ def test_missing_required_field_raises(self, snapshot_path) -> None:
+ gym_tools = load_snapshots([snapshot_path])
+ with pytest.raises(ValueError, match="system_prompt"):
+ convert_task({"user_prompt": "x", "gym_servers_config": [{}]}, "t", "csm", "oracle", gym_tools)
+
+ def test_strip_private_keys(self) -> None:
+ stripped = strip_private_keys(dict(TASK))
+ assert "_comment" not in stripped
+ assert "_description" not in stripped["verifiers"][0]
+
+ def test_convert_writes_jsonl(self, snapshot_path, tmp_path) -> None:
+ output = tmp_path / "out.jsonl"
+ num_written = convert([("task_1", dict(TASK))], [snapshot_path], "csm", "oracle", output)
+ assert num_written == 1
+ rows = [json.loads(line) for line in output.read_text().splitlines()]
+ assert rows[0]["verifier_metadata"]["task_id"] == "task_1"
+
+ def test_duplicate_tools_resolve_in_task_gym_order(self, tmp_path) -> None:
+ """EOG parity: tools merge per task in the TASK's gym_servers_config order, so a
+ duplicate-named tool maps to the task's FIRST gym that provides it — regardless of
+ snapshot load order. (A fixed global merge would route hybrid tool calls to gyms
+ that aren't even part of the task's session.)"""
+ snapshot_a = tmp_path / "a.json"
+ snapshot_b = tmp_path / "b.json"
+ snapshot_a.write_text(json.dumps({"gym_name": "gym-a", "tools": [{"name": "shared", "inputSchema": {}}]}))
+ snapshot_b.write_text(json.dumps({"gym_name": "gym-b", "tools": [{"name": "shared", "inputSchema": {}}]}))
+ gym_tools = load_snapshots([snapshot_a, snapshot_b]) # load order: a, b
+
+ task = {
+ "selected_tools": ["shared"],
+ "restricted_tools": [],
+ # Task uses gym-b FIRST -> shared must map to gym-b, not snapshot-order gym-a.
+ "gym_servers_config": [
+ {"mcp_server_name": "gym-b", "mcp_server_url": "http://b"},
+ {"mcp_server_name": "gym-a", "mcp_server_url": "http://a"},
+ ],
+ }
+ tools, task_tool_to_gym = build_tools_for_task(task, gym_tools)
+ assert [t["name"] for t in tools] == ["shared"]
+ assert task_tool_to_gym == {"shared": "gym-b"}
+
+ def test_task_gym_without_snapshot_warns_and_skips(self, snapshot_path) -> None:
+ gym_tools = load_snapshots([snapshot_path])
+ task = dict(TASK) | {
+ "gym_servers_config": TASK["gym_servers_config"]
+ + [{"mcp_server_name": "unknown-gym", "mcp_server_url": "http://x"}]
+ }
+ tools, task_tool_to_gym = build_tools_for_task(task, gym_tools)
+ # Known gym's tools still resolve; unknown gym contributes nothing.
+ assert task_tool_to_gym == {"update_entitlement": "sn-csm-server"}
diff --git a/resources_servers/enterpriseops_gym/tests/test_export_eval_telemetry.py b/resources_servers/enterpriseops_gym/tests/test_export_eval_telemetry.py
new file mode 100644
index 0000000000..bfb7663861
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/test_export_eval_telemetry.py
@@ -0,0 +1,146 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import pytest
+
+from resources_servers.enterpriseops_gym.export_eval_telemetry import (
+ align_tool_latencies,
+ export_rows,
+ render_question,
+)
+
+
+def make_turn(turn, input_tokens, output_tokens, cached=0, tools=(), text="", start=0, end=0):
+ return {
+ "turn": turn,
+ "timestamp": f"2026-07-07T00:00:0{turn}+00:00",
+ "duration_ms": 100.0,
+ "model": "test-model",
+ "input_tokens": input_tokens,
+ "output_tokens": output_tokens,
+ "cached_input_tokens": cached,
+ "reasoning_tokens": 0,
+ "tool_call_names": list(tools),
+ "num_tool_calls": len(tools),
+ "assistant_text": text,
+ "output_start_index": start,
+ "output_end_index": end,
+ }
+
+
+def make_row(task_index, rollout_index, turns, latencies, reward=1.0, output=None):
+ return {
+ "_ng_task_index": task_index,
+ "_ng_rollout_index": rollout_index,
+ "reward": reward,
+ "verifier_metadata": {"task_id": f"task_{task_index}", "domain": "csm", "mode": "oracle"},
+ "responses_create_params": {
+ "input": [
+ {"role": "system", "content": "Policy."},
+ {"role": "user", "content": "Do the thing."},
+ ]
+ },
+ "response": {"output": output or []},
+ "turns": turns,
+ "num_turns": len(turns),
+ "tool_latencies_ms": latencies,
+ }
+
+
+class TestExport:
+ def test_full_schema_two_passes(self) -> None:
+ # Pass 1: two turns (tool call then final answer); pass 2: single-turn answer.
+ pass1 = make_row(
+ 0,
+ 0,
+ turns=[
+ make_turn(0, 1000, 20, cached=0, tools=("update_entitlement",), start=0, end=2),
+ make_turn(1, 1500, 30, cached=990, text="Done.", start=2, end=3),
+ ],
+ latencies=[{"tool": "update_entitlement", "gym": "g", "latency_ms": 42.0}],
+ )
+ pass2 = make_row(0, 1, turns=[make_turn(0, 900, 15, text="Nope.")], latencies=[], reward=0.0)
+
+ rows = export_rows([pass1, pass2])
+ assert len(rows) == 3
+
+ first, second, third = rows
+ assert first["task_id"] == "task_0"
+ assert first["trial_name"] == "task_0.1-of-2.default"
+ assert third["trial_name"] == "task_0.2-of-2.default"
+
+ # Turn indexing and totals
+ assert (first["turn"], first["num_turns"]) == (0, 2)
+ assert (second["turn"], second["num_turns"]) == (1, 2)
+
+ # Token accounting: stacked == input (no compaction), new = input - cached
+ assert first["input_length"] == 1000 and first["stacked_input"] == 1000
+ assert second["cached input length"] == 990
+ assert second["new input length"] == 510
+
+ # Tool fields
+ assert first["tool_call names"] == "update_entitlement"
+ assert first["num_steps"] == 1
+ assert first["per-tool latency"] == 42
+ assert second["per-tool latency"] is None
+
+ # Completion / resolution semantics
+ assert first["task_complete"] is False
+ assert second["task_complete"] is True
+ assert first["is_resolved"] is True and third["is_resolved"] is False
+
+ # Compaction fields are explicitly null (no compaction in this harness)
+ for field in ("tokensBefore", "tokensAfter", "content before compaction", "content after compaction"):
+ assert first[field] is None
+
+ # Prompt rendering
+ assert "[system]\nPolicy." in first["question"]
+ assert "[user]\nDo the thing." in first["question"]
+ assert second["answer"] == "Done."
+ assert second["timestamp"] == "2026-07-07T00:00:01+00:00"
+
+ def test_answer_includes_reasoning_summaries(self) -> None:
+ output = [
+ {"type": "reasoning", "summary": [{"type": "summary_text", "text": "I should update it."}]},
+ {"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "Done."}]},
+ ]
+ row = make_row(0, 0, turns=[make_turn(0, 10, 5, text="Done.", start=0, end=2)], latencies=[], output=output)
+ exported = export_rows([row])[0]
+ assert exported["answer"] == "I should update it.\n\nDone."
+
+ def test_malformed_tool_calls_align_to_null_without_shifting(self) -> None:
+ # Turn 0 issued two calls but the second was malformed (never reached the proxy);
+ # turn 1 issued one good call. Latencies: [good_call_A, good_call_C].
+ turns = [
+ make_turn(0, 10, 5, tools=("tool_a", "tool_b")),
+ make_turn(1, 10, 5, tools=("tool_c",)),
+ ]
+ latencies = [
+ {"tool": "tool_a", "gym": "g", "latency_ms": 10.0},
+ {"tool": "tool_c", "gym": "g", "latency_ms": 30.0},
+ ]
+ aligned = align_tool_latencies(turns, latencies)
+ assert aligned[0][0]["tool"] == "tool_a"
+ assert aligned[0][1] is None # malformed: no latency, no shift
+ assert aligned[1][0]["tool"] == "tool_c"
+
+ def test_rows_without_turns_raise_helpful_error(self) -> None:
+ row = make_row(0, 0, turns=[], latencies=[])
+ del row["turns"]
+ with pytest.raises(ValueError, match="turn_logging_agent"):
+ export_rows([row])
+
+ def test_render_question_handles_structured_content(self) -> None:
+ text = render_question({"input": [{"role": "user", "content": [{"type": "input_text", "text": "hi"}]}]})
+ assert text.startswith("[user]")
diff --git a/resources_servers/enterpriseops_gym/tests/test_verifier_engine.py b/resources_servers/enterpriseops_gym/tests/test_verifier_engine.py
new file mode 100644
index 0000000000..5ade6628b7
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/tests/test_verifier_engine.py
@@ -0,0 +1,210 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Unit + golden-parity tests for the ported EOG verifier engine.
+
+The golden file (fixtures/verifier_parity_golden.json) is generated by running the SAME
+input cases through the ORIGINAL EnterpriseOps-Gym engine (see generate_parity_golden.py,
+run inside the EOG checkout's venv). These tests pin our port to upstream byte-for-byte.
+"""
+
+import asyncio
+import json
+from pathlib import Path
+
+import pytest
+
+from resources_servers.enterpriseops_gym.verifier_engine import (
+ VerifierEngine,
+ compare_values,
+ extract_json_from_judge_response,
+ extract_llm_content,
+ extract_value_from_sql_result,
+)
+
+
+FIXTURES_DIR = Path(__file__).parent / "fixtures"
+CASES_PATH = FIXTURES_DIR / "verifier_parity_cases.json"
+GOLDEN_PATH = FIXTURES_DIR / "verifier_parity_golden.json"
+
+
+@pytest.mark.skipif(
+ not GOLDEN_PATH.exists(),
+ reason="verifier_parity_golden.json missing — generate it with generate_parity_golden.py in the EOG venv",
+)
+class TestGoldenParity:
+ """Assert our port matches the original EOG engine's outputs on shared fixture cases."""
+
+ def test_extraction_matches_upstream(self) -> None:
+ cases = json.loads(CASES_PATH.read_text())
+ golden = json.loads(GOLDEN_PATH.read_text())
+ assert len(golden["extraction"]) == len(cases["extraction"])
+ for case, expected in zip(cases["extraction"], golden["extraction"]):
+ assert extract_value_from_sql_result(case) == expected, f"extraction mismatch for case: {case}"
+
+ def test_comparison_matches_upstream(self) -> None:
+ cases = json.loads(CASES_PATH.read_text())
+ golden = json.loads(GOLDEN_PATH.read_text())
+ assert len(golden["comparison"]) == len(cases["comparison"])
+ for case, expected in zip(cases["comparison"], golden["comparison"]):
+ actual = compare_values(case["actual"], case["expected"], case["comparison_type"])
+ assert actual == expected, f"comparison mismatch for case: {case}"
+
+
+class TestExtractionSemantics:
+ """Direct pins of the quirkier upstream extraction rules."""
+
+ def test_single_row_single_column_unwraps_scalar(self) -> None:
+ assert extract_value_from_sql_result({"success": True, "result": {"data": [{"c": "h24x7"}]}}) == "h24x7"
+
+ def test_single_row_multi_column_returns_row_dict(self) -> None:
+ assert extract_value_from_sql_result({"success": True, "result": {"data": [{"a": 1, "b": 2}]}}) == {
+ "a": 1,
+ "b": 2,
+ }
+
+ def test_failure_with_mcp_content_returns_text(self) -> None:
+ result = {"success": False, "result": {"content": [{"type": "text", "text": "boom"}]}}
+ assert extract_value_from_sql_result(result) == "boom"
+
+ def test_failure_without_content_returns_none(self) -> None:
+ assert extract_value_from_sql_result({"success": False}) is None
+
+
+class TestComparisonSemantics:
+ def test_equals_is_type_strict(self) -> None:
+ # Upstream uses plain ==, so 0 != "0". SQL ints vs JSON strings matter for parity.
+ assert compare_values(0, "0", "equals")["passed"] is False
+ assert compare_values(0, 0, "equals")["passed"] is True
+
+ def test_incomparable_types_fail_gracefully(self) -> None:
+ result = compare_values("5", 3, "greater_than")
+ assert result["passed"] is False
+ assert result["details"].startswith("Comparison error")
+
+ def test_unknown_comparison_type(self) -> None:
+ result = compare_values(1, 1, "approximately")
+ assert result["passed"] is False
+ assert "Unknown comparison type" in result["details"]
+
+
+class TestJudgeParsing:
+ def test_fenced_json_block(self) -> None:
+ text = 'Sure!\n```json\n{"score": 9, "reasoning": "good"}\n```'
+ assert json.loads(extract_json_from_judge_response(text)) == {"score": 9, "reasoning": "good"}
+
+ def test_bare_fence(self) -> None:
+ text = '```\n{"score": 3, "reasoning": "bad"}\n```'
+ assert json.loads(extract_json_from_judge_response(text)) == {"score": 3, "reasoning": "bad"}
+
+ def test_extract_llm_content_priority(self) -> None:
+ assert extract_llm_content({"content": "a", "text": "b"}) == "a"
+ assert extract_llm_content({"text": "b"}) == "b"
+ assert extract_llm_content({"response": "c"}) == "c"
+
+
+class _FakeSQLClient:
+ """Minimal stand-in for MCPGymClient's run_sql in judge tests."""
+
+ def __init__(self, result):
+ self._result = result
+
+ async def run_sql(self, query, database_id, context=None):
+ return self._result
+
+
+class TestResponseCheckJudge:
+ def _engine(self, judge_text: str) -> VerifierEngine:
+ async def judge_fn(system_prompt: str, user_prompt: str) -> str:
+ return judge_text
+
+ client = _FakeSQLClient({"success": True, "result": {"data": [{"case_id": 1233}]}})
+ return VerifierEngine(gym_clients={"g": client}, judge_fn=judge_fn)
+
+ def _verifier(self) -> dict:
+ return {
+ "verifier_type": "response_check",
+ "name": "answer_check",
+ "gym_name": "g",
+ "validation_config": {
+ "sql_query": "SELECT case_id FROM cases;",
+ "comparison_prompt": "Does the response mention the case id?",
+ "minimum_comparison_value": 7,
+ },
+ }
+
+ def test_judge_pass(self) -> None:
+ engine = self._engine('```json\n{"score": 9, "reasoning": "mentions 1233"}\n```')
+ result = asyncio.run(
+ engine.execute_verifier(self._verifier(), {"content": "Case 1233 filed."}, "db1", None, gym_name="g")
+ )
+ assert result["passed"] is True
+ assert result["score"] == 9
+
+ def test_judge_fail_below_minimum(self) -> None:
+ engine = self._engine('{"score": 4, "reasoning": "vague"}')
+ result = asyncio.run(
+ engine.execute_verifier(self._verifier(), {"content": "Done."}, "db1", None, gym_name="g")
+ )
+ assert result["passed"] is False
+
+ def test_no_judge_configured_fails_cleanly(self) -> None:
+ client = _FakeSQLClient({"success": True, "result": {"data": []}})
+ engine = VerifierEngine(gym_clients={"g": client}, judge_fn=None)
+ result = asyncio.run(engine.execute_verifier(self._verifier(), {"content": "x"}, "db1", None, gym_name="g"))
+ assert result["passed"] is False
+ assert "Judge comparison failed" in result["error"]
+
+ def test_unsupported_verifier_type(self) -> None:
+ engine = VerifierEngine(gym_clients={"g": _FakeSQLClient({})}, judge_fn=None)
+ result = asyncio.run(engine.execute_verifier({"verifier_type": "nope"}, {}, "db1"))
+ assert result == {"passed": False, "error": "Unsupported verifier type: nope"}
+
+
+class TestRunVerifiersCollapse:
+ def test_collapse_and_skip_semantics(self) -> None:
+ client = _FakeSQLClient({"success": True, "result": {"data": [{"c": 1}]}})
+ engine = VerifierEngine(gym_clients={"g": client}, judge_fn=None)
+
+ verifiers = [
+ # Fails (1 != 2), then a same-named pass overwrites it.
+ {
+ "verifier_type": "database_state",
+ "name": "dup",
+ "gym_name": "g",
+ "validation_config": {"query": "q", "expected_value": 2},
+ },
+ {
+ "verifier_type": "database_state",
+ "name": "dup",
+ "gym_name": "g",
+ "validation_config": {"query": "q", "expected_value": 1},
+ },
+ # Unknown gym -> skipped entirely.
+ {
+ "verifier_type": "database_state",
+ "name": "orphan",
+ "gym_name": "missing",
+ "validation_config": {"query": "q", "expected_value": 1},
+ },
+ ]
+ collapsed, all_results = asyncio.run(
+ engine.run_verifiers(verifiers, {"content": ""}, {"g": "db1"}, {"g": None})
+ )
+
+ assert list(collapsed.keys()) == ["dup"]
+ assert collapsed["dup"]["passed"] is True # last-per-name wins
+ assert len(all_results) == 3
+ assert [r["skipped"] for r in all_results] == [False, False, True]
+ assert [r["result"]["passed"] for r in all_results] == [False, True, False]
diff --git a/resources_servers/enterpriseops_gym/verifier_engine.py b/resources_servers/enterpriseops_gym/verifier_engine.py
new file mode 100644
index 0000000000..1bf1001e6c
--- /dev/null
+++ b/resources_servers/enterpriseops_gym/verifier_engine.py
@@ -0,0 +1,426 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""EnterpriseOps-Gym verifier engine, ported from ``benchmark/verifier.py`` + ``benchmark/executor.py``.
+
+PARITY WARNING: the extraction, comparison, judge-prompt, and result-collapse semantics below
+are intentionally line-for-line ports of EnterpriseOps-Gym (Apache 2.0), including its quirks:
+
+- ``_extract_value_from_sql_result`` has finicky single-row/single-column unwrapping rules.
+- ``compare_values`` uses loose Python comparisons (``0 != "0"``).
+- Verifier results are collapsed into a dict keyed by verifier *name*; tasks reuse names, so
+ duplicate-named verifiers OVERWRITE each other and only the LAST one per name is scored
+ (executor.py:474 upstream). The published leaderboard numbers use this behavior.
+- Verifiers referencing an unknown ``gym_name`` are skipped entirely (not counted).
+
+Do not "fix" these here — parity with the upstream benchmark is the point. The strict,
+every-verifier-counts variant is computed separately for RL reward shaping.
+
+Deviations from upstream (behavior-preserving): verifiers execute concurrently instead of
+sequentially (they are independent reads; collapse is applied in config order afterwards),
+and the LLM judge call is injected as an async callable instead of a LangChain client.
+"""
+
+import asyncio
+import json
+import logging
+from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple
+
+from resources_servers.enterpriseops_gym.mcp_client import MCPGymClient
+
+
+logger = logging.getLogger(__name__)
+
+
+JudgeFn = Callable[[str, str], Awaitable[str]]
+
+
+# Verbatim EOG judge system prompt (benchmark/verifier.py::_compare_with_llm).
+JUDGE_SYSTEM_PROMPT = """You are an AI judge evaluating the quality and accuracy of an AI assistant's response.
+Compare the database query result with the AI's response and rate how well they match.
+Provide a score from 1-10 where:
+- 1-3: Poor match, incorrect or missing information
+- 4-6: Partial match, some correct information
+- 7-8: Good match, mostly correct
+- 9-10: Excellent match, fully accurate
+
+Respond with ONLY a JSON object in this format:
+{
+ "score": ,
+ "reasoning": ""
+}"""
+
+
+def extract_value_from_sql_result(result: dict) -> Any:
+ """Extract the actual value from SQL query result (verbatim EOG port)."""
+ if not result:
+ return None
+
+ # If the result itself is not successful, check for error content
+ if not result.get("success"):
+ # Try to extract error message from MCP response format
+ result_data = result.get("result", {})
+ if isinstance(result_data, dict) and "content" in result_data:
+ content = result_data["content"]
+ if isinstance(content, list) and len(content) > 0:
+ for item in content:
+ if isinstance(item, dict) and item.get("type") == "text":
+ return item.get("text", "Error")
+ return None
+
+ result_data = result.get("result", {})
+
+ # Handle different result formats from MCP sql-runner
+ if isinstance(result_data, dict):
+ # If result has 'data' field (common format)
+ if "data" in result_data:
+ data = result_data["data"]
+ if isinstance(data, list) and len(data) > 0:
+ # If single row with single column, return the value directly
+ if len(data) == 1 and isinstance(data[0], dict) and len(data[0]) == 1:
+ return list(data[0].values())[0]
+ # If single row with multiple columns, return the row dict
+ elif len(data) == 1:
+ return data[0]
+ # Multiple rows, return the full result
+ else:
+ return data
+ return data
+
+ # If result has 'rows' field
+ elif "rows" in result_data:
+ rows = result_data["rows"]
+ if isinstance(rows, list) and len(rows) > 0:
+ # Single value from single row
+ if len(rows) == 1 and isinstance(rows[0], dict) and len(rows[0]) == 1:
+ return list(rows[0].values())[0]
+ # Single row as list
+ elif len(rows) == 1 and isinstance(rows[0], list) and len(rows[0]) == 1:
+ return rows[0][0]
+ # Single row (dict or list)
+ elif len(rows) == 1:
+ return rows[0]
+ # Multiple rows
+ else:
+ return rows
+ return rows
+
+ # If result has 'content' field (MCP error format)
+ elif "content" in result_data:
+ content = result_data["content"]
+ if isinstance(content, list) and len(content) > 0:
+ # Extract text from content array
+ for item in content:
+ if isinstance(item, dict) and item.get("type") == "text":
+ return item.get("text", result_data)
+ return content
+
+ # Direct result format (nested 'result' field)
+ elif "result" in result_data:
+ return result_data["result"]
+
+ # Return as-is if we can't extract anything specific
+ return result_data
+
+
+def compare_values(actual: Any, expected: Any, comparison_type: str) -> Dict[str, Any]:
+ """Compare actual vs expected values (verbatim EOG port)."""
+ try:
+ if comparison_type == "equals":
+ passed = actual == expected
+ elif comparison_type == "greater_than":
+ passed = actual > expected
+ elif comparison_type == "less_than":
+ passed = actual < expected
+ elif comparison_type == "contains":
+ passed = expected in str(actual)
+ else:
+ return {
+ "passed": False,
+ "details": f"Unknown comparison type: {comparison_type}",
+ }
+
+ return {
+ "passed": passed,
+ "details": f"Comparison {comparison_type}: {actual} vs {expected}",
+ }
+
+ except Exception as e:
+ return {"passed": False, "details": f"Comparison error: {e}"}
+
+
+def extract_llm_content(model_response: Dict[str, Any]) -> str:
+ """Extract text content from LLM response (verbatim EOG port)."""
+ if "content" in model_response:
+ return str(model_response["content"])
+ elif "text" in model_response:
+ return str(model_response["text"])
+ elif "response" in model_response:
+ return str(model_response["response"])
+
+ return str(model_response)
+
+
+def extract_json_from_judge_response(response_text: str) -> str:
+ """Strip markdown code fences from a judge response (verbatim EOG parsing)."""
+ if "```json" in response_text:
+ response_text = response_text.split("```json")[1].split("```")[0].strip()
+ elif "```" in response_text:
+ response_text = response_text.split("```")[1].split("```")[0].strip()
+ return response_text
+
+
+class VerifierEngine:
+ """Multi-gym verifier engine. Supports: database_state, response_check, tool_execution."""
+
+ def __init__(self, gym_clients: Dict[str, MCPGymClient], judge_fn: Optional[JudgeFn] = None) -> None:
+ self.gym_clients = gym_clients
+ self.judge_fn = judge_fn
+
+ def _get_mcp_client_for_gym(self, gym_name: Optional[str] = None) -> MCPGymClient:
+ """Get the appropriate MCP client for a gym, or default (first), as EOG does."""
+ if gym_name and gym_name in self.gym_clients:
+ return self.gym_clients[gym_name]
+ return next(iter(self.gym_clients.values()))
+
+ async def execute_verifier(
+ self,
+ verifier: Dict[str, Any],
+ model_response: Dict[str, Any],
+ database_id: Optional[str],
+ context: Optional[Dict[str, Any]] = None,
+ gym_name: Optional[str] = None,
+ ) -> Dict[str, Any]:
+ """Execute a single verifier (EOG dispatch semantics)."""
+ verifier_type = verifier.get("verifier_type")
+ validation_config = verifier.get("validation_config") or {}
+
+ if verifier_type == "database_state":
+ return await self._execute_database_state_verifier(validation_config, database_id, context, gym_name)
+ elif verifier_type == "response_check":
+ return await self._execute_response_check_verifier(
+ validation_config, model_response, database_id, context, gym_name
+ )
+ elif verifier_type == "tool_execution":
+ return self._execute_tool_execution_verifier(validation_config, model_response)
+ else:
+ return {
+ "passed": False,
+ "error": f"Unsupported verifier type: {verifier_type}",
+ }
+
+ async def _execute_database_state_verifier(
+ self,
+ validation_config: Dict[str, Any],
+ database_id: Optional[str],
+ context: Optional[Dict[str, Any]] = None,
+ gym_name: Optional[str] = None,
+ ) -> Dict[str, Any]:
+ sql_query = validation_config.get("query")
+ expected_value = validation_config.get("expected_value")
+ comparison_type = validation_config.get("comparison_type", "equals")
+
+ if not sql_query:
+ return {"passed": False, "error": "No SQL query provided"}
+
+ client = self._get_mcp_client_for_gym(gym_name)
+ result = await client.run_sql(sql_query, database_id, context)
+
+ if not result["success"]:
+ return {
+ "passed": False,
+ "error": f"SQL query failed: {result.get('error')}",
+ "query": sql_query,
+ }
+
+ actual_value = extract_value_from_sql_result(result)
+ comparison_result = compare_values(actual_value, expected_value, comparison_type)
+
+ return {
+ "passed": comparison_result["passed"],
+ "expected": expected_value,
+ "actual": actual_value,
+ "comparison_type": comparison_type,
+ "query": sql_query,
+ "details": comparison_result.get("details"),
+ }
+
+ async def _execute_response_check_verifier(
+ self,
+ validation_config: Dict[str, Any],
+ model_response: Dict[str, Any],
+ database_id: Optional[str],
+ context: Optional[Dict[str, Any]] = None,
+ gym_name: Optional[str] = None,
+ ) -> Dict[str, Any]:
+ sql_query = validation_config.get("sql_query")
+ comparison_prompt = validation_config.get("comparison_prompt")
+ minimum_comparison_value = validation_config.get("minimum_comparison_value", 7)
+
+ if not sql_query or not comparison_prompt:
+ return {"passed": False, "error": "Missing sql_query or comparison_prompt"}
+
+ client = self._get_mcp_client_for_gym(gym_name)
+ sql_result = await client.run_sql(sql_query, database_id, context)
+
+ if not sql_result["success"]:
+ return {
+ "passed": False,
+ "error": f"SQL query failed: {sql_result.get('error')}",
+ }
+
+ llm_response_text = extract_llm_content(model_response)
+ return await self._compare_with_llm(sql_result, llm_response_text, comparison_prompt, minimum_comparison_value)
+
+ def _execute_tool_execution_verifier(
+ self, validation_config: Dict[str, Any], model_response: Dict[str, Any]
+ ) -> Dict[str, Any]:
+ """Execute tool execution verifier (verbatim EOG port)."""
+ selected_tools = validation_config.get("selected_tools", [])
+ minimum_tool_calls = validation_config.get("minimum_tool_calls", 1)
+
+ tools_called = []
+ if "tool_calls" in model_response and model_response["tool_calls"]:
+ tools_called = [tc["name"] for tc in model_response["tool_calls"]]
+
+ missing_tools = [tool for tool in selected_tools if tool not in tools_called]
+ passed = len(missing_tools) == 0 and len(tools_called) >= minimum_tool_calls
+
+ return {
+ "passed": passed,
+ "selected_tools": selected_tools,
+ "tools_called": tools_called,
+ "missing_tools": missing_tools,
+ "minimum_tool_calls": minimum_tool_calls,
+ "actual_tool_calls": len(tools_called),
+ }
+
+ async def _compare_with_llm(
+ self,
+ sql_result: Dict[str, Any],
+ llm_response: str,
+ comparison_prompt: str,
+ minimum_score: int,
+ ) -> Dict[str, Any]:
+ """Use LLM as judge to compare SQL result with LLM response (verbatim EOG prompts/parsing)."""
+ sql_result_str = json.dumps(sql_result.get("result", {}), indent=2)
+
+ user_prompt = f"""Database Query Result:
+{sql_result_str}
+
+AI Assistant Response:
+{llm_response}
+
+Comparison Task:
+{comparison_prompt}
+
+Please provide your judgment as JSON."""
+
+ try:
+ if self.judge_fn is None:
+ raise RuntimeError("No judge model configured (set judge_model_server in the resources server config)")
+
+ response_text = await self.judge_fn(JUDGE_SYSTEM_PROMPT, user_prompt)
+ response_text = extract_json_from_judge_response(response_text)
+
+ judge_result = json.loads(response_text)
+ score = judge_result.get("score", 0)
+ reasoning = judge_result.get("reasoning", "")
+
+ passed = score >= minimum_score
+
+ return {
+ "passed": passed,
+ "score": score,
+ "minimum_score": minimum_score,
+ "reasoning": reasoning,
+ "sql_result": sql_result_str,
+ "llm_response": llm_response,
+ }
+
+ except Exception as e:
+ logger.error(f"LLM judge comparison failed: {e}")
+ return {"passed": False, "error": f"Judge comparison failed: {e}"}
+
+ async def run_verifiers(
+ self,
+ verifiers: List[Dict[str, Any]],
+ model_response: Dict[str, Any],
+ gym_databases: Dict[str, Optional[str]],
+ gym_contexts: Dict[str, Optional[Dict[str, Any]]],
+ ) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
+ """Run all verifiers and collapse results with EOG executor semantics.
+
+ Returns:
+ (verification_results, all_verifier_results)
+
+ verification_results: EOG-parity dict keyed by verifier name — duplicate names
+ overwrite in config order, so only the LAST verifier per name is scored.
+ Verifiers with an unknown gym_name are skipped (absent), as upstream.
+ all_verifier_results: every verifier's result (strict view), in config order.
+ """
+
+ async def _run_one(index: int, verifier: Dict[str, Any]) -> Dict[str, Any]:
+ verifier_name = verifier.get("name") or f"verifier_{index + 1}"
+ gym_name = verifier.get("gym_name")
+
+ # Gym resolution, mirroring executor._run_verifiers:
+ # - gym_name set and known -> that gym's database/context
+ # - gym_name set and unknown -> skip the verifier entirely (not counted)
+ # - gym_name unset -> upstream falls back to the legacy single-gym database
+ # (None for multi-gym configs); we use the single gym when unambiguous.
+ skipped = False
+ database_id: Optional[str] = None
+ context: Optional[Dict[str, Any]] = None
+ if gym_name:
+ if gym_name in gym_databases:
+ database_id = gym_databases[gym_name]
+ context = gym_contexts.get(gym_name)
+ else:
+ logger.warning(f"Gym '{gym_name}' not found in gym_servers_config!")
+ skipped = True
+ elif len(gym_databases) == 1:
+ only_gym = next(iter(gym_databases))
+ database_id = gym_databases[only_gym]
+ context = gym_contexts.get(only_gym)
+
+ if skipped:
+ return {
+ "index": index,
+ "name": verifier_name,
+ "gym_name": gym_name,
+ "skipped": True,
+ "result": {"passed": False, "error": f"Gym '{gym_name}' not found in configuration"},
+ }
+
+ result = await self.execute_verifier(verifier, model_response, database_id, context, gym_name=gym_name)
+ return {
+ "index": index,
+ "name": verifier_name,
+ "gym_name": gym_name,
+ "skipped": False,
+ "result": result,
+ }
+
+ all_verifier_results = await asyncio.gather(*(_run_one(i, v) for i, v in enumerate(verifiers)))
+
+ # EOG-parity collapse: dict keyed by name, insertion/overwrite in config order,
+ # skipped verifiers omitted entirely.
+ verification_results: Dict[str, Any] = {}
+ for entry in all_verifier_results:
+ if entry["skipped"]:
+ continue
+ verification_results[entry["name"]] = entry["result"]
+
+ return verification_results, list(all_verifier_results)
diff --git a/responses_api_agents/turn_logging_agent/README.md b/responses_api_agents/turn_logging_agent/README.md
new file mode 100644
index 0000000000..2fcfe56939
--- /dev/null
+++ b/responses_api_agents/turn_logging_agent/README.md
@@ -0,0 +1,57 @@
+# Turn Logging Agent
+
+A drop-in variant of `simple_agent` that records **per-turn telemetry** while running the
+identical agent loop (same max-steps, tool-calling, and termination behavior — validated
+live against `simple_agent` with no outcome drift; see
+`resources_servers/enterpriseops_gym/PARITY.md` §3, run C).
+
+## Why
+
+The stock `simple_agent` aggregates usage across the whole rollout, which discards
+per-turn timings and zeroes `cached_tokens` / reasoning-token details. Eval workflows that
+analyze turn-level behavior (latency breakdowns, prefix-cache hit rates, tool-call timing)
+need those numbers preserved per model call.
+
+## What it records
+
+For every agent turn: timestamp, wall-clock duration, input/output/**cached**/reasoning
+token counts, tool names called, and the output-slice indices into the final response.
+Turn records are correlated to model calls via a private Responses `metadata` key
+(`_turn_log_id`, stripped before the request reaches the model server) and attached as
+`turns` on the verify response, so they land in collected rollout rows.
+
+`resources_servers/enterpriseops_gym/export_eval_telemetry.py` shows a downstream
+consumer: it flattens `turns` into a per-turn JSONL telemetry schema.
+
+## Usage
+
+Wire it like `simple_agent` — it is environment-agnostic. Example config
+(`resources_servers/enterpriseops_gym/configs/enterpriseops_gym_turnlog.yaml` adds it
+alongside a standard stack):
+
+```yaml
+my_turn_logging_agent:
+ responses_api_agents:
+ turn_logging_agent:
+ entrypoint: app.py
+ max_steps: 50
+ resources_server:
+ type: resources_servers
+ name: my_resources_server
+ model_server:
+ type: responses_api_models
+ name: policy_model
+ datasets:
+ - name: example
+ type: example
+ jsonl_fpath: resources_servers/my_resources_server/data/example.jsonl
+```
+
+Collect rollouts with `+agent_name=my_turn_logging_agent`; each output row's verify
+response carries the `turns` list.
+
+## Tests
+
+```bash
+gym env test +entrypoint=responses_api_agents/turn_logging_agent
+```
diff --git a/responses_api_agents/turn_logging_agent/__init__.py b/responses_api_agents/turn_logging_agent/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/responses_api_agents/turn_logging_agent/app.py b/responses_api_agents/turn_logging_agent/app.py
new file mode 100644
index 0000000000..c42e6c9793
--- /dev/null
+++ b/responses_api_agents/turn_logging_agent/app.py
@@ -0,0 +1,304 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""SimpleAgent with per-turn telemetry.
+
+Behaviorally identical agent loop to ``responses_api_agents/simple_agent`` (same cookie
+threading, malformed-tool-call handling, and termination conditions), but it additionally:
+
+- records one telemetry record per model API call (turn): ISO timestamp, wall duration,
+ per-turn input/output/total tokens, CACHED input tokens (which simple_agent zeroes in
+ its aggregate — the per-turn values here come straight from the model server), reasoning
+ tokens, tool-call names, and the slice of the final output list the turn produced;
+- aggregates usage without discarding cached/reasoning token details;
+- attaches the turn list to the final verify response (``turns``, ``num_turns``,
+ ``trial_started_at``, ``trial_finished_at``) so rollout JSONL rows carry full per-turn
+ traces for downstream telemetry export.
+
+Correlation between the ``/run`` request and its inner ``/v1/responses`` call uses the
+Responses API ``metadata`` field (key ``_turn_log_id``), which is stripped before any
+model call.
+"""
+
+import json
+from datetime import datetime, timezone
+from time import monotonic
+from typing import Any, Dict, List, Optional
+from uuid import uuid4
+
+from fastapi import Request, Response
+from pydantic import ConfigDict, Field, ValidationError
+
+from nemo_gym.base_resources_server import BaseVerifyResponse
+from nemo_gym.base_responses_api_agent import Body
+from nemo_gym.openai_utils import (
+ NeMoGymEasyInputMessage,
+ NeMoGymFunctionCallOutput,
+ NeMoGymResponse,
+ NeMoGymResponseCreateParamsNonStreaming,
+ NeMoGymResponseFunctionToolCall,
+ NeMoGymResponseOutputMessage,
+)
+from nemo_gym.server_utils import get_response_json, raise_for_status
+from responses_api_agents.simple_agent.app import SimpleAgent, SimpleAgentConfig, SimpleAgentRunRequest
+
+
+TURN_LOG_ID_METADATA_KEY = "_turn_log_id"
+
+
+class TurnLoggingAgentConfig(SimpleAgentConfig):
+ pass
+
+
+class TurnLoggingVerifyResponse(BaseVerifyResponse):
+ model_config = ConfigDict(extra="allow")
+ turns: List[Dict[str, Any]]
+ num_turns: int
+ trial_started_at: Optional[str]
+ trial_finished_at: Optional[str]
+
+
+class TurnLoggingAgent(SimpleAgent):
+ config: TurnLoggingAgentConfig
+
+ # In-memory turn logs keyed by correlation id; entries are popped by run().
+ turn_logs: Dict[str, List[Dict[str, Any]]] = Field(default_factory=dict)
+
+ @staticmethod
+ def _strip_metadata(
+ body: NeMoGymResponseCreateParamsNonStreaming,
+ ) -> tuple[NeMoGymResponseCreateParamsNonStreaming, Optional[str]]:
+ """Extract the correlation id and rebuild the params without metadata set at all
+ (so it is never forwarded to the model server)."""
+ turn_log_id = (body.metadata or {}).get(TURN_LOG_ID_METADATA_KEY)
+ if body.metadata is not None:
+ body_dict = body.model_dump(exclude_unset=True)
+ body_dict.pop("metadata", None)
+ body = NeMoGymResponseCreateParamsNonStreaming.model_validate(body_dict)
+ return body, turn_log_id
+
+ async def responses(
+ self,
+ request: Request,
+ response: Response,
+ body: NeMoGymResponseCreateParamsNonStreaming = Body(),
+ ) -> NeMoGymResponse:
+ # PARITY NOTE: this loop mirrors simple_agent.SimpleAgent.responses step for step
+ # (cookie threading, malformed-argument handling, termination). Keep it in sync.
+ body, turn_log_id = self._strip_metadata(body.model_copy(deep=True))
+
+ if isinstance(body.input, str):
+ body.input = [NeMoGymEasyInputMessage(role="user", content=body.input)]
+
+ turns: List[Dict[str, Any]] = []
+ new_outputs = []
+ usage = None
+ cached_tokens_total = 0
+ reasoning_tokens_total = 0
+ step = 0
+ model_server_cookies = None
+ resources_server_cookies = request.cookies
+
+ while True:
+ step += 1
+ new_body = body.model_copy(update={"input": body.input + new_outputs})
+
+ turn_started_at = datetime.now(timezone.utc).isoformat()
+ turn_t0 = monotonic()
+ model_response = await self.server_client.post(
+ server_name=self.config.model_server.name,
+ url_path=self.url_path_for_request("/v1/responses", request),
+ json=new_body,
+ cookies=model_server_cookies,
+ )
+ await raise_for_status(model_response)
+ model_response_json = await get_response_json(model_response)
+ model_server_cookies = model_response.cookies
+ try:
+ model_response = NeMoGymResponse.model_validate(model_response_json)
+ except ValidationError as e:
+ raise RuntimeError(
+ f"Received an invalid response from model server: {json.dumps(model_response_json)}"
+ ) from e
+ turn_duration_ms = round((monotonic() - turn_t0) * 1000, 1)
+
+ output = model_response.output
+ output_start_index = len(new_outputs)
+ new_outputs.extend(output)
+
+ # Per-turn usage, straight from the model server (cached tokens intact).
+ turn_usage = model_response.usage
+ turn_input = turn_usage.input_tokens if turn_usage else 0
+ turn_output = turn_usage.output_tokens if turn_usage else 0
+ turn_cached = 0
+ turn_reasoning = 0
+ if turn_usage and turn_usage.input_tokens_details:
+ turn_cached = turn_usage.input_tokens_details.cached_tokens or 0
+ if turn_usage and turn_usage.output_tokens_details:
+ turn_reasoning = turn_usage.output_tokens_details.reasoning_tokens or 0
+ cached_tokens_total += turn_cached
+ reasoning_tokens_total += turn_reasoning
+
+ if not usage:
+ usage = model_response.usage
+ model_response.usage = None
+
+ if usage and model_response.usage:
+ usage.input_tokens += model_response.usage.input_tokens
+ usage.output_tokens += model_response.usage.output_tokens
+ usage.total_tokens += model_response.usage.total_tokens
+
+ all_fn_calls: List[NeMoGymResponseFunctionToolCall] = [o for o in output if o.type == "function_call"]
+ all_output_messages: List[NeMoGymResponseOutputMessage] = [
+ o for o in output if o.type == "message" and o.role == "assistant"
+ ]
+
+ turn_assistant_text = "".join(
+ content.text
+ for message in all_output_messages
+ for content in message.content
+ if getattr(content, "type", None) == "output_text"
+ )
+
+ turn_record = {
+ "turn": step - 1,
+ "timestamp": turn_started_at,
+ "duration_ms": turn_duration_ms,
+ "model": model_response.model,
+ "response_id": model_response.id,
+ "status": model_response.status,
+ "incomplete_reason": model_response.incomplete_details.reason
+ if model_response.incomplete_details
+ else None,
+ "input_tokens": turn_input,
+ "output_tokens": turn_output,
+ "cached_input_tokens": turn_cached,
+ "reasoning_tokens": turn_reasoning,
+ "tool_call_names": [fn_call.name for fn_call in all_fn_calls],
+ "num_tool_calls": len(all_fn_calls),
+ "assistant_text": turn_assistant_text,
+ "output_start_index": output_start_index,
+ "output_end_index": None, # set below, after tool outputs are appended
+ }
+ turns.append(turn_record)
+
+ if model_response.incomplete_details:
+ turn_record["output_end_index"] = len(new_outputs)
+ break
+
+ if not all_fn_calls and all_output_messages:
+ turn_record["output_end_index"] = len(new_outputs)
+ break
+
+ for output_function_call in all_fn_calls:
+ try:
+ parsed_arguments = json.loads(output_function_call.arguments)
+ except (json.JSONDecodeError, TypeError) as e:
+ tool_response = NeMoGymFunctionCallOutput(
+ type="function_call_output",
+ call_id=output_function_call.call_id,
+ output=json.dumps({"error": f"Invalid tool call arguments: {e!r}"}),
+ )
+ new_outputs.append(tool_response)
+ continue
+
+ api_response = await self.server_client.post(
+ server_name=self.config.resources_server.name,
+ url_path=f"/{output_function_call.name}",
+ json=parsed_arguments,
+ cookies=resources_server_cookies,
+ )
+ resources_server_cookies = api_response.cookies
+
+ tool_response = NeMoGymFunctionCallOutput(
+ type="function_call_output",
+ call_id=output_function_call.call_id,
+ output=(await api_response.content.read()).decode(),
+ )
+ new_outputs.append(tool_response)
+
+ turn_record["output_end_index"] = len(new_outputs)
+
+ if self.config.max_steps and step >= self.config.max_steps:
+ break
+
+ for k, v in (*resources_server_cookies.items(), *model_server_cookies.items()):
+ response.set_cookie(k, v)
+
+ # Restore token detail sums that simple_agent zeroes out.
+ if usage:
+ if usage.input_tokens_details:
+ usage.input_tokens_details.cached_tokens = cached_tokens_total
+ if usage.output_tokens_details:
+ usage.output_tokens_details.reasoning_tokens = reasoning_tokens_total
+
+ if turn_log_id:
+ self.turn_logs[turn_log_id] = turns
+
+ model_response.output = new_outputs
+ model_response.usage = usage
+ return model_response
+
+ async def run(self, request: Request, body: SimpleAgentRunRequest) -> TurnLoggingVerifyResponse:
+ cookies = request.cookies
+
+ seed_session_response = await self.server_client.post(
+ server_name=self.config.resources_server.name,
+ url_path="/seed_session",
+ json=body.model_dump(),
+ cookies=cookies,
+ )
+ await raise_for_status(seed_session_response)
+ cookies = seed_session_response.cookies
+
+ # Correlate this trial's inner /v1/responses call so we can attach its turn log.
+ turn_log_id = uuid4().hex
+ responses_create_params = body.responses_create_params.model_copy(
+ update={"metadata": {TURN_LOG_ID_METADATA_KEY: turn_log_id}}
+ )
+
+ response = await self.server_client.post(
+ server_name=self.config.name,
+ url_path=self.url_path_for_run("/v1/responses", body),
+ json=responses_create_params,
+ cookies=cookies,
+ )
+ await raise_for_status(response)
+ cookies = response.cookies
+
+ verify_request_dict = body.model_dump() | {"response": await get_response_json(response)}
+
+ verify_response = await self.server_client.post(
+ server_name=self.config.resources_server.name,
+ url_path="/verify",
+ json=verify_request_dict,
+ cookies=cookies,
+ )
+ await raise_for_status(verify_response)
+ verify_response_dict = await get_response_json(verify_response)
+
+ turns = self.turn_logs.pop(turn_log_id, [])
+ return TurnLoggingVerifyResponse.model_validate(
+ verify_response_dict
+ | {
+ "turns": turns,
+ "num_turns": len(turns),
+ "trial_started_at": turns[0]["timestamp"] if turns else None,
+ "trial_finished_at": turns[-1]["timestamp"] if turns else None,
+ }
+ )
+
+
+if __name__ == "__main__":
+ TurnLoggingAgent.run_webserver()
diff --git a/responses_api_agents/turn_logging_agent/requirements.txt b/responses_api_agents/turn_logging_agent/requirements.txt
new file mode 100644
index 0000000000..00ed83213e
--- /dev/null
+++ b/responses_api_agents/turn_logging_agent/requirements.txt
@@ -0,0 +1 @@
+-e nemo-gym[dev] @ ../../
diff --git a/responses_api_agents/turn_logging_agent/tests/test_app.py b/responses_api_agents/turn_logging_agent/tests/test_app.py
new file mode 100644
index 0000000000..33f3da1d89
--- /dev/null
+++ b/responses_api_agents/turn_logging_agent/tests/test_app.py
@@ -0,0 +1,200 @@
+# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import json
+from unittest.mock import AsyncMock, MagicMock
+
+from fastapi.testclient import TestClient
+from pytest import MonkeyPatch
+
+from nemo_gym.server_utils import ServerClient
+from responses_api_agents.simple_agent.app import ModelServerRef, ResourcesServerRef
+from responses_api_agents.turn_logging_agent.app import (
+ TurnLoggingAgent,
+ TurnLoggingAgentConfig,
+)
+
+
+def make_config() -> TurnLoggingAgentConfig:
+ return TurnLoggingAgentConfig(
+ host="0.0.0.0",
+ port=8080,
+ entrypoint="",
+ name="turn_logging_agent",
+ model_server=ModelServerRef(type="responses_api_models", name="model server"),
+ resources_server=ResourcesServerRef(type="resources_servers", name="resources server"),
+ )
+
+
+def usage(input_tokens: int, output_tokens: int, cached: int = 0, reasoning: int = 0) -> dict:
+ return {
+ "input_tokens": input_tokens,
+ "output_tokens": output_tokens,
+ "total_tokens": input_tokens + output_tokens,
+ "input_tokens_details": {"cached_tokens": cached},
+ "output_tokens_details": {"reasoning_tokens": reasoning},
+ }
+
+
+def model_response(output: list, usage_dict: dict, response_id: str = "resp_1") -> dict:
+ return {
+ "id": response_id,
+ "created_at": 0.0,
+ "model": "dummy_model",
+ "object": "response",
+ "output": output,
+ "parallel_tool_calls": True,
+ "tool_choice": "auto",
+ "tools": [],
+ "usage": usage_dict,
+ }
+
+
+FN_CALL = {
+ "type": "function_call",
+ "id": "fc_1",
+ "call_id": "call_1",
+ "name": "get_weather",
+ "arguments": json.dumps({"city": "SF"}),
+ "status": "completed",
+}
+FINAL_MESSAGE = {
+ "type": "message",
+ "id": "msg_1",
+ "role": "assistant",
+ "status": "completed",
+ "content": [{"type": "output_text", "text": "It is cold.", "annotations": []}],
+}
+
+
+def http_mock(payload) -> MagicMock:
+ mock = MagicMock()
+ mock.read = AsyncMock(return_value=json.dumps(payload))
+ mock.content.read = AsyncMock(return_value=json.dumps(payload).encode())
+ mock.cookies = {}
+ return mock
+
+
+class TestTurnLogging:
+ def test_rollout_prefix_carried_onto_model_calls(self) -> None:
+ # A /ng-rollout/-prefixed self-call must re-apply the capture-correlation
+ # prefix to downstream model calls, mirroring simple_agent's url_path_for_request.
+ server = TurnLoggingAgent(config=make_config(), server_client=MagicMock(spec=ServerClient))
+ client = TestClient(server.setup_webserver())
+
+ turn = model_response([FINAL_MESSAGE], usage(100, 10))
+ server.server_client.post = AsyncMock(side_effect=[http_mock(turn)])
+
+ result = client.post(
+ "/ng-rollout/rid-7/v1/responses",
+ json={"input": [{"role": "user", "content": "hi"}]},
+ )
+ assert result.status_code == 200, result.text
+
+ model_call = server.server_client.post.call_args_list[0]
+ assert model_call.kwargs["url_path"] == "/ng-rollout/rid-7/v1/responses"
+
+ def test_two_turn_loop_captures_per_turn_telemetry(self) -> None:
+ server = TurnLoggingAgent(config=make_config(), server_client=MagicMock(spec=ServerClient))
+ client = TestClient(server.setup_webserver())
+
+ turn1 = model_response([FN_CALL], usage(1000, 20, cached=0), "resp_turn1")
+ tool_result = {"content": [{"type": "text", "text": "cold"}], "isError": False}
+ turn2 = model_response([FINAL_MESSAGE], usage(1200, 30, cached=950, reasoning=5), "resp_turn2")
+ server.server_client.post = AsyncMock(side_effect=[http_mock(turn1), http_mock(tool_result), http_mock(turn2)])
+
+ result = client.post(
+ "/v1/responses",
+ json={
+ "input": [{"role": "user", "content": "weather in SF?"}],
+ "metadata": {"_turn_log_id": "trial-42"},
+ },
+ )
+ assert result.status_code == 200, result.text
+ body = result.json()
+
+ # Aggregate usage sums across turns WITHOUT zeroing cached/reasoning details.
+ assert body["usage"]["input_tokens"] == 2200
+ assert body["usage"]["output_tokens"] == 50
+ assert body["usage"]["input_tokens_details"]["cached_tokens"] == 950
+ assert body["usage"]["output_tokens_details"]["reasoning_tokens"] == 5
+
+ # Metadata was stripped before every model call.
+ for call in server.server_client.post.call_args_list:
+ if call.kwargs.get("server_name") == "model server":
+ assert call.kwargs["json"].metadata is None
+
+ # Per-turn telemetry captured under the correlation id.
+ turns = server.turn_logs["trial-42"]
+ assert len(turns) == 2
+ first, second = turns
+ assert first["turn"] == 0
+ assert first["tool_call_names"] == ["get_weather"]
+ assert first["input_tokens"] == 1000
+ assert first["cached_input_tokens"] == 0
+ assert first["response_id"] == "resp_turn1"
+ assert first["timestamp"].endswith("+00:00")
+ # Turn 1 slice covers the function_call plus its tool output.
+ assert (first["output_start_index"], first["output_end_index"]) == (0, 2)
+ assert second["turn"] == 1
+ assert second["input_tokens"] == 1200
+ assert second["cached_input_tokens"] == 950
+ assert second["reasoning_tokens"] == 5
+ assert second["assistant_text"] == "It is cold."
+ assert second["tool_call_names"] == []
+ assert (second["output_start_index"], second["output_end_index"]) == (2, 3)
+
+ # The final trajectory matches simple_agent semantics: fn_call, tool output, message.
+ assert [o["type"] for o in body["output"]] == ["function_call", "function_call_output", "message"]
+
+ def test_run_attaches_turns_to_verify_response(self, monkeypatch: MonkeyPatch) -> None:
+ server = TurnLoggingAgent(config=make_config(), server_client=MagicMock(spec=ServerClient))
+ client = TestClient(server.setup_webserver())
+
+ fixed_id = MagicMock()
+ fixed_id.hex = "fixed-trial-id"
+ monkeypatch.setattr("responses_api_agents.turn_logging_agent.app.uuid4", lambda: fixed_id)
+
+ # Pre-fill the turn log the (mocked) inner /v1/responses call would have produced.
+ server.turn_logs["fixed-trial-id"] = [
+ {"turn": 0, "timestamp": "2026-07-07T00:00:00+00:00"},
+ {"turn": 1, "timestamp": "2026-07-07T00:00:09+00:00"},
+ ]
+
+ responses_create_params = {"input": [{"role": "user", "content": "hi"}]}
+ final_response = model_response([FINAL_MESSAGE], usage(10, 5))
+ verify_payload = {
+ "responses_create_params": responses_create_params,
+ "response": final_response,
+ "reward": 1.0,
+ }
+ server.server_client.post = AsyncMock(
+ side_effect=[http_mock({}), http_mock(final_response), http_mock(verify_payload)]
+ )
+
+ result = client.post("/run", json={"responses_create_params": responses_create_params})
+ assert result.status_code == 200, result.text
+ body = result.json()
+
+ assert body["reward"] == 1.0
+ assert body["num_turns"] == 2
+ assert [t["turn"] for t in body["turns"]] == [0, 1]
+ assert body["trial_started_at"] == "2026-07-07T00:00:00+00:00"
+ assert body["trial_finished_at"] == "2026-07-07T00:00:09+00:00"
+
+ # The inner /v1/responses call carried the correlation metadata...
+ inner_call = server.server_client.post.call_args_list[1]
+ assert inner_call.kwargs["json"].metadata == {"_turn_log_id": "fixed-trial-id"}
+ # ...and the log entry was popped after use.
+ assert server.turn_logs == {}