> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veval.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Start sending traces to Veval in minutes.

## Install

<CodeGroup>
  ```bash C# theme={null}
  dotnet add package Veval.Sdk
  ```

  ```bash Python theme={null}
  pip install veval-sdk
  ```

  ```bash Node theme={null}
  npm install @veval/sdk
  ```
</CodeGroup>

## Get your API key

Go to [dashboard.veval.dev](https://dashboard.veval.dev) → Settings → API Keys.

***

## Part 1: Minimal trace (no LLM required)

The simplest possible integration — wrap any async operation and it appears in your dashboard.

<CodeGroup>
  ```csharp C# theme={null}
  using Veval.Sdk;

  var veval = new VevalSdk(new VevalOptions
  {
      ApiKey   = "YOUR_API_KEY",
      Endpoint = "https://api.veval.dev",
  });

  var result = await veval.RunAsync("my-agent", async ctx =>
  {
      var output = await ctx.TrackStepAsync("summarize", input: "hello world", async () =>
      {
          // replace with your real LLM call
          return "Hello, world!";
      });

      return output;
  });

  veval.Dispose();
  ```

  ```python Python theme={null}
  import asyncio
  from veval import VevalSdk, VevalOptions

  veval = VevalSdk(VevalOptions(api_key="YOUR_API_KEY"))

  async def main():
      async def my_agent(ctx):
          async def summarize():
              # replace with your real LLM call
              return "Hello, world!"

          return await ctx.track_step_async("summarize", "hello world", summarize)

      result = await veval.run_async("my-agent", my_agent)

  asyncio.run(main())
  ```

  ```javascript Node theme={null}
  import { VevalSdk } from "@veval/sdk";

  const veval = new VevalSdk({ apiKey: "YOUR_API_KEY" });

  const result = await veval.runAsync("my-agent", async (ctx) => {
    const output = await ctx.trackStepAsync("summarize", "hello world", async () => {
      // replace with your real LLM call
      return "Hello, world!";
    });
    return output;
  });
  ```
</CodeGroup>

That's it. Open your dashboard — you'll see a trace with one step.

***

## Part 2: Service pattern (recommended for production)

For real agents, pass the execution context into your service class so every LLM call is tracked automatically.

<CodeGroup>
  ```csharp C# theme={null}
  // Your agent service accepts VevalExecutionContext
  public class MyAgentService(IVevalSdk veval, AnthropicClient claude)
  {
      public async Task<string> ExecuteAsync(VevalExecutionContext ctx)
      {
          var answer = await ctx.TrackStepAsync("answer", ctx.Input, async handle =>
          {
              var response = await claude.Messages.CreateAsync(...);

              // attach LLM metadata to the step
              handle.SetMeta("model",      response.Model);
              handle.SetMeta("tokens_in",  response.Usage.InputTokens);
              handle.SetMeta("tokens_out", response.Usage.OutputTokens);
              handle.SetMeta("cost_usd",   ComputeCost(response.Usage));

              return response.Content[0].Text;
          });

          return answer;
      }
  }

  // Wire it up
  var veval   = new VevalSdk(new VevalOptions { ApiKey = "YOUR_API_KEY" });
  var service = new MyAgentService(veval, claude);

  var result = await veval.RunAsync("my-agent", service.ExecuteAsync, input: userMessage);
  ```

  ```python Python theme={null}
  # Your agent service accepts VevalExecutionContext
  class MyAgentService:
      def __init__(self, anthropic):
          self._anthropic = anthropic

      async def execute_async(self, ctx):
          async def step(handle):
              response = await self._anthropic.messages.create(...)

              # attach LLM metadata to the step
              handle.set_meta("model",      response.model)
              handle.set_meta("tokens_in",  response.usage.input_tokens)
              handle.set_meta("tokens_out", response.usage.output_tokens)
              handle.set_meta("cost_usd",   compute_cost(response.usage))

              return response.content[0].text

          return await ctx.track_step_async("answer", ctx.input, step)

  # Wire it up
  veval   = VevalSdk(VevalOptions(api_key="YOUR_API_KEY"))
  service = MyAgentService(anthropic)

  result = await veval.run_async("my-agent", service.execute_async, input=user_message)
  ```

  ```javascript Node theme={null}
  // Your agent service accepts VevalExecutionContext
  class MyAgentService {
    constructor(anthropic) {
      this.anthropic = anthropic;
    }

    async execute(ctx) {
      return await ctx.trackStepAsync("answer", ctx.input, async (handle) => {
        const response = await this.anthropic.messages.create({ ... });

        // attach LLM metadata to the step
        handle.setMeta("model",      response.model);
        handle.setMeta("tokens_in",  response.usage.input_tokens);
        handle.setMeta("tokens_out", response.usage.output_tokens);
        handle.setMeta("cost_usd",   computeCost(response.usage));

        return response.content[0].text;
      });
    }
  }

  // Wire it up
  const veval   = new VevalSdk({ apiKey: "YOUR_API_KEY" });
  const service = new MyAgentService(anthropic);

  const result = await veval.runAsync("my-agent", (ctx) => service.execute(ctx), userMessage);
  ```
</CodeGroup>

<Note>
  Injecting `IVevalSdk` (the interface) lets you swap in `VevalTestSdk` in tests — no live LLM calls, no API cost. See [Replay](/guides/replay).
</Note>
