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

# Create log

This guide shows you how to log any type of LLM request to Keywords AI using the **universal input/output design** that supports all span types.

<Warning>
  **Log size limit: 20MB**

  Each log payload has a maximum size limit of 20MB. This includes the `input`, `output`, and all other fields combined. Logs exceeding this limit will be rejected.
</Warning>

## Input/Output

**Keywords AI uses universal `input` and `output` fields across all span types.**

* **Chat completions**: Messages arrays
* **Embeddings**: Text strings or arrays
* **Transcriptions**: Audio metadata → text
* **Speech**: Text → audio
* **Workflows/Tasks**: Any custom data structure
* **Agent operations**: Complex nested objects

**How it works:**

1. You provide `input` and `output` fields in any structure (string, object, array, etc.)
2. Set `log_type` to indicate span type (`"chat"`, `"embedding"`, `"workflow"`, etc.)
3. Keywords AI automatically extracts type-specific fields for backward compatibility
4. Your data is stored efficiently and retrieved with both universal and type-specific fields

For complete `log_type` specifications, see [log types](/get-started/observability_data_model#log-types).

<Note>
  ### Legacy field support

  For backward compatibility, Keywords AI still supports legacy fields:

  <ParamField body="prompt_messages" type="array">
    **Legacy field.** Use `input` instead.
  </ParamField>

  <ParamField body="completion_message" type="object">
    **Legacy field.** Use `output` instead.
  </ParamField>
</Note>

## Request body

### Core fields

<ParamField body="input" type="string | object | array">
  Universal input field for the span. Structure depends on `log_type`:

  * **Chat**: JSON string of messages array or messages array directly
  * **Embedding**: Text string or array of strings
  * **Workflow/Task**: Any JSON-serializable structure
  * **Transcription**: Audio file reference or metadata object
  * **Speech**: Text string or TTS configuration object

  See the **Span Types** section below for complete specifications.

  <Accordion title="Example for Chat">
    ```json theme={"system"}
    "input": "[{\"role\":\"system\",\"content\":\"You are helpful.\"},{\"role\":\"user\",\"content\":\"Hello\"}]"
    ```
  </Accordion>

  <Accordion title="Example for Embedding">
    ```json theme={"system"}
    "input": "Keywords AI is an LLM observability platform"
    ```
  </Accordion>

  <Accordion title="Example for Workflow">
    ```json theme={"system"}
    "input": "{\"query\":\"Help with order #12345\",\"context\":{\"user_id\":\"123\"}}"
    ```
  </Accordion>
</ParamField>

<ParamField body="output" type="string | object | array">
  Universal output field for the span. Structure depends on `log_type`:

  * **Chat**: JSON string of completion message or message object directly
  * **Embedding**: Array of vector embeddings
  * **Workflow/Task**: Any JSON-serializable result structure
  * **Transcription**: Transcribed text string
  * **Speech**: Audio file reference or base64 audio data

  <Accordion title="Example for Chat">
    ```json theme={"system"}
    "output": "{\"role\":\"assistant\",\"content\":\"Hello! How can I help you?\"}"
    ```
  </Accordion>

  <Accordion title="Example for Embedding">
    ```json theme={"system"}
    "output": "[0.123, -0.456, 0.789, ...]"
    ```
  </Accordion>
</ParamField>

<ParamField body="log_type" type="string" default="chat">
  Type of span being logged. Determines how `input` and `output` are parsed.

  **Supported types:**

  * `"chat"` - Chat completion requests (default)
  * `"completion"` - Legacy completion requests
  * `"response"` - OpenAI Response API
  * `"embedding"` - Embedding generation
  * `"transcription"` - Speech-to-text
  * `"speech"` - Text-to-speech
  * `"workflow"` or `"agent"` - Workflow/agent execution
  * `"task"` or `"tool"` - Task/tool execution
  * `"function"` - Function call
  * `"generation"` - Generation span
  * `"handoff"` - Agent handoff
  * `"guardrail"` - Safety check
  * `"custom"` - Custom span type

  <Accordion title="Default Behavior">
    If not specified, defaults to `"chat"`. For chat types, the system automatically extracts `prompt_messages` and `completion_message` from `input` and `output` for backward compatibility.

    For complete specifications of each type, see [log types](/get-started/observability_data_model#log-types).
  </Accordion>
</ParamField>

<ParamField body="model" type="string">
  The model used for the inference. Optional but recommended for chat/completion/embedding types.

  <Accordion title="Example">
    ```json theme={"system"}
    "model": "gpt-4o-mini"
    ```
  </Accordion>
</ParamField>

### Telemetry

Performance metrics and cost tracking for monitoring LLM efficiency.

<ParamField body="usage" type="object">
  Token usage information for the request.

  <AccordionGroup>
    <Accordion title="Properties">
      <ParamField body="prompt_tokens" type="integer">
        Number of tokens in the prompt/input.
      </ParamField>

      <ParamField body="completion_tokens" type="integer">
        Number of tokens in the completion/output.
      </ParamField>

      <ParamField body="total_tokens" type="integer">
        Total tokens (prompt + completion).
      </ParamField>

      <ParamField body="prompt_tokens_details" type="object">
        Detailed breakdown of prompt tokens (e.g., cached tokens).
      </ParamField>

      <ParamField body="cache_creation_prompt_tokens" type="integer">
        For Anthropic models: tokens used to create the cache.
      </ParamField>
    </Accordion>

    <Accordion title="Example">
      ```json theme={"system"}
      {
        "usage": {
          "prompt_tokens": 150,
          "completion_tokens": 85,
          "total_tokens": 235,
          "prompt_tokens_details": {
            "cached_tokens": 10
          }
        }
      }
      ```
    </Accordion>
  </AccordionGroup>
</ParamField>

<ParamField body="cost" type="float">
  Cost of the inference in US dollars. If not provided, will be calculated automatically based on model pricing.
</ParamField>

<ParamField body="latency" type="float">
  Total request latency in seconds (replaces deprecated `generation_time`).

  <Note>
    Previously called `generation_time`. For backward compatibility, both field names are supported.
  </Note>
</ParamField>

<ParamField body="time_to_first_token" type="float">
  Time to first token (TTFT) in seconds. Useful for streaming responses and voice AI applications.

  <Note>
    Previously called `ttft`. Both field names are supported.
  </Note>
</ParamField>

<ParamField body="tokens_per_second" type="float">
  Generation speed in tokens per second.
</ParamField>

### Metadata

Custom tracking and identification parameters for advanced analytics and filtering.

<ParamField body="metadata" type="object">
  You can add any key-value pair to this metadata field for your reference. Useful for custom analytics and filtering.

  <Accordion title="Example">
    ```json theme={"system"}
    {
      "metadata": {
        "language": "en",
        "environment": "production",
        "version": "v1.0.0",
        "feature": "chat_support",
        "user_tier": "premium"
      }
    }
    ```
  </Accordion>
</ParamField>

<ParamField body="customer_identifier" type="string">
  An identifier for the customer that invoked this request. Helps with visualizing user activities. See [customer identifier details](/documentation/products/users/customer-identifier).

  <Accordion title="Example">
    ```json theme={"system"}
    "customer_identifier": "user_123"
    ```
  </Accordion>
</ParamField>

<ParamField body="customer_params" type="object">
  Extended customer information (alternative to individual customer fields).

  <AccordionGroup>
    <Accordion title="Properties">
      <ParamField body="customer_identifier" type="string">
        Customer identifier.
      </ParamField>

      <ParamField body="name" type="string">
        Customer name.
      </ParamField>

      <ParamField body="email" type="string">
        Customer email.
      </ParamField>
    </Accordion>

    <Accordion title="Example">
      ```json theme={"system"}
      {
        "customer_params": {
          "customer_identifier": "customer_123",
          "name": "John Doe",
          "email": "john.doe@example.com"
        }
      }
      ```
    </Accordion>
  </AccordionGroup>
</ParamField>

<ParamField body="thread_identifier" type="string">
  A unique identifier for the conversation thread. Useful for multi-turn conversations.
</ParamField>

<ParamField body="custom_identifier" type="string">
  Same functionality as `metadata`, but indexed for faster querying.

  <Accordion title="Example">
    ```json theme={"system"}
    "custom_identifier": "ticket_12345"
    ```
  </Accordion>
</ParamField>

<ParamField body="group_identifier" type="string">
  Group identifier. Use to group related logs together.
</ParamField>

### Workflow & tracing

Parameters for distributed tracing and workflow tracking.

<ParamField body="trace_unique_id" type="string">
  Unique identifier for the trace. Used to link multiple spans together in distributed tracing.
</ParamField>

<ParamField body="span_workflow_name" type="string">
  Name of the workflow this span belongs to.
</ParamField>

<ParamField body="span_name" type="string">
  Name of this specific span/task within the workflow.
</ParamField>

<ParamField body="span_parent_id" type="string">
  ID of the parent span. Used to build the trace hierarchy.
</ParamField>

## Advanced parameters

### Tool calls and function calling

<ParamField body="tools" type="array">
  A list of tools the model may call. Currently, only functions are supported as a tool.

  <AccordionGroup>
    <Accordion title="Properties">
      <ParamField body="type" type="string" required>
        The type of the tool. Currently, only `function` is supported.
      </ParamField>

      <ParamField body="function" type="object" required>
        <Accordion title="Properties">
          <ParamField body="name" type="string" required>
            The name of the function.
          </ParamField>

          <ParamField body="description" type="string">
            A description of what the function does.
          </ParamField>

          <ParamField body="parameters" type="object">
            The parameters the function accepts.
          </ParamField>
        </Accordion>
      </ParamField>
    </Accordion>

    <Accordion title="Example">
      ```json theme={"system"}
      "tools": [
          {
              "type": "function",
              "function": {
                  "name": "get_current_weather",
                  "description": "Get the current weather in a given location",
                  "parameters": {
                      "type": "object",
                      "properties": {
                          "location": {
                              "type": "string",
                              "description": "The city and state, e.g. San Francisco, CA"
                          },
                          "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                      },
                      "required": ["location"]
                  }
              }
          }
      ]
      ```
    </Accordion>
  </AccordionGroup>
</ParamField>

<ParamField body="tool_choice" type="string | object">
  Controls which (if any) tool is called by the model. Can be `"none"`, `"auto"`, or an object specifying a specific tool.

  <Accordion title="Example">
    ```json theme={"system"}
    "tool_choice": {
        "type": "function",
        "function": {
            "name": "get_current_weather"
        }
    }
    ```
  </Accordion>
</ParamField>

### Response configuration

<ParamField body="response_format" type="object">
  Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs.

  <Accordion title="Possible types">
    * **Text**: `{ "type": "text" }` - Default response format
    * **JSON Schema**: `{ "type": "json_schema", "json_schema": {...} }` - Structured outputs
    * **JSON Object**: `{ "type": "json_object" }` - Legacy JSON format
  </Accordion>
</ParamField>

### Model configuration

<ParamField body="temperature" type="number" default={1}>
  Controls randomness in the output (0-2). Higher values produce more random responses.
</ParamField>

<ParamField body="top_p" type="number" default={1}>
  Nucleus sampling parameter. Alternative to temperature.
</ParamField>

<ParamField body="frequency_penalty" type="number">
  Penalizes tokens based on their frequency in the text so far.
</ParamField>

<ParamField body="presence_penalty" type="number">
  Penalizes tokens based on whether they appear in the text so far.
</ParamField>

<ParamField body="max_tokens" type="integer">
  Maximum number of tokens to generate.
</ParamField>

<ParamField body="stop" type="array[string]">
  Stop sequences where generation will stop.
</ParamField>

### Error handling and status

<ParamField body="status_code" type="integer" default={200}>
  The HTTP status code for the request. Default is 200 (success).

  <Accordion title="Supported status codes">
    All valid HTTP status codes are supported: `200`, `201`, `400`, `401`, `403`, `404`, `429`, `500`, `502`, `503`, `504`, etc.
  </Accordion>
</ParamField>

<ParamField body="error_message" type="string">
  Error message if the request failed. Default is empty string.
</ParamField>

<ParamField body="warnings" type="string | object">
  Any warnings that occurred during the request.
</ParamField>

<ParamField body="status" type="string">
  Request status. Common values: `"success"`, `"error"`.
</ParamField>

### Additional configuration

<ParamField body="stream" type="boolean" default={false}>
  Whether the response was streamed.
</ParamField>

<ParamField body="prompt_id" type="string">
  ID of the prompt template used. See [Prompts documentation](/documentation/products/prompt_management/creating_prompts/create_prompt).
</ParamField>

<ParamField body="prompt_name" type="string">
  Name of the prompt template.
</ParamField>

<ParamField body="is_custom_prompt" type="boolean" default={false}>
  Whether the prompt is a custom prompt. Set to `true` if using custom `prompt_id`.
</ParamField>

<ParamField body="timestamp" type="string">
  ISO 8601 timestamp when the request completed.

  <Accordion title="Example">
    ```json theme={"system"}
    "timestamp": "2025-01-01T10:30:00Z"
    ```
  </Accordion>
</ParamField>

<ParamField body="start_time" type="string">
  ISO 8601 timestamp when the request started.
</ParamField>

<ParamField body="full_request" type="object">
  The full request object. Useful for logging additional configuration parameters.

  <Note>
    Tool calls and other nested objects will be automatically extracted from `full_request`.
  </Note>
</ParamField>

<ParamField body="full_response" type="object">
  The full response object from the model provider.
</ParamField>

### Pricing configuration

<ParamField body="prompt_unit_price" type="number">
  Custom price per 1M prompt tokens. Used for self-hosted or fine-tuned models.

  <Accordion title="Example">
    ```json theme={"system"}
    "prompt_unit_price": 0.0042  // $0.0042 per 1M tokens
    ```
  </Accordion>
</ParamField>

<ParamField body="completion_unit_price" type="number">
  Custom price per 1M completion tokens. Used for self-hosted or fine-tuned models.

  <Accordion title="Example">
    ```json theme={"system"}
    "completion_unit_price": 0.0042  // $0.0042 per 1M tokens
    ```
  </Accordion>
</ParamField>

### API controls

<ParamField body="keywordsai_api_controls" type="object">
  Control the behavior of the Keywords AI logging API.

  <AccordionGroup>
    <Accordion title="Properties">
      <ParamField body="block" type="boolean" default={true}>
        If `false`, the server immediately returns initialization status without waiting for log completion.
      </ParamField>
    </Accordion>

    <Accordion title="Example">
      ```json theme={"system"}
      {
        "keywordsai_api_controls": {
          "block": true
        }
      }
      ```
    </Accordion>
  </AccordionGroup>
</ParamField>

<ParamField body="positive_feedback" type="boolean">
  Whether the user liked the output. `true` means positive feedback.
</ParamField>
