# Firetiger Documentation > Firetiger is a REST API platform (JSON-over-POST, AIP conventions, Basic auth) for configuring autonomous agents that monitor software systems using telemetry data and connected tools. ## Table of Contents - **Concepts**: Agents, Integrations, Telemetry, Deployments, Issues, Knowledge - **Guides**: OpenTelemetry Integration, MCP Server, Agent Webhooks, BigQuery Integration, incident.io Workflows, Monitoring your deploys, Connect to a Private Database with Tailscale - **Integrations**: PostgreSQL, MySQL, ClickHouse, AWS, GCP, AWS CloudWatch Logs, AWS ECS Events, CloudFront Kinesis Integration, Cloudflare Workers Integration, Cloudflare Logpush Integration, GitHub, GitHub Webhooks, Incident.io, Pylon, Slack, SendGrid Event Webhooks, Google Postmaster Tools, Vector, Datadog Agent, DataDog Log Forwarding, HTTP, MCP Servers, OpenAPI, AWS VPC Peering, Tailscale - **Deployment Options**: SaaS, BYOC: AWS, BYOC: GCP - **Account Management**: Google Workspace, API Keys - **API Reference**: Agents, Connections, Customers, Deployments, Investigations, Issues, Known Issues, Monitoring Plans, Notes, Tags, Runbooks, Triggers, Agent, Session, Connection, Customer, Deployment, Investigation, Issue, Known Issue, Monitoring Plan, Note, Runbook, Tag, Trigger, Activity --- # Concepts Core concepts and terminology in Firetiger. ## Agents ## What are Agents? Firetiger Agents are autonomous LLM-driven workers that you can configure to manage your software systems. They are defined by a **plan**, run in response to **triggers**, and use a configured set of **tools**. You can see your agents at [/agents]({{ site.ui_url }}/agents). You can create as many Agents as you want. Treat agents as lightweight operators. It's common to make agents for ad-hoc tasks, not just persistent operational roles. ## What can Agents do? Agents can be granted access to [your telemetry](./telemetry.txt) and [connected tools](./integrations.txt). They run in an isolated sandbox with shell scripting and Python. By connecting a [HTTP Integration](../integrations/custom/http.txt), you can give them the ability to access specific addresses over the network, too. Typical uses of Agents include: - Writing a weekly analytics report - Investigating root causes of issues and posting updates on ticketing systems - Running playbooks of remediation commands in response to issues - Detecting and notifying code owners of issues - Running post-deploy tasks ## How to make an Agent Firetiger Agents are created conversationally in a planning session. To make one, go to [the Agent creation page]({{ site.ui_url }}/agents/new), and describe what you'd like the agent to do in high-level terms. The agent is initially in a draft state as you refine its goals and objectives. The planner that you're conversing with is able to use tools, and grant access to tools the actual realized agent instance it's creating with you. You can tell the planner to try executing the agent as much as you like to verify that it does what you expect, and then tell it to "enable" the agent to put it into live service. The planner will take care of all the details of configuring your agent, including writing a detailed prompt, setting up the triggers that control when it runs, and granting it access to only the tools it needs. Once it's ready, it'll summarize its results for you: You can always come back to the same planner by going to the 'plan' tab under your configured agent: ## When do Agents run? Agents are run in response to **Triggers**. There are three sorts of triggers. ### Webhook Triggers All agents are automatically configured with a trigger ID that can be used to invoke them with a webhook. This invocation can include a message that can be passed to the agent which can have any text content. The generated trigger ID is visible on the Agent Details page: The webhook invocations need to be authenticated. See [API keys](../account-management/api_keys.txt) for details on getting an API key. For more details on running webhook triggers, see [Running Agents With Webhooks](../guides/agent-webhooks.txt). ### Scheduled Triggers Agents can be configured to run on a repeated schedule. This is expressed as a [`cron`](https://en.wikipedia.org/wiki/Cron) schedule. This is capable of expressing common intervals, like running every 15 minutes, every hour, or at the start of each week. ### Post-Deploy Triggers Agents can be configured to run after a particular bit of code is shipped in a [Deployment](./deployments.txt). Post-Deploy triggers require a [GitHub Integration](../integrations/developer-tools/github.txt). They are configured to watch for a particular Git commit (or any of its descendants), in a particular repo, for a particular environment. When that commit-repo-environment triplet is first seen, the trigger will fire, with an optional delay. This can be used to set up sophisticated post-deploy orchestration workflows, like poking a new API and watching the chain of logs in a real production service. ## Viewing Agent runs You can see the individual executions of your agent under the Sessions tab: These sessions can finish in one of three ways: - "Done" sessions are ones that completed their mission successfully. Hooray! - "Issue Found" sessions are ones that detected and reported some operational issue. They might have still accomplished their goal, but they flagged something for the [Issue subsystem](./issues.txt) to triage. - "Aborted" sessions are ones that, for some reason, were unable to do their job. This could be a data access issue or broken connection, and these usually indicate that some human intervention is needed to fix up the agent that ran the session. In any case, you can click into a session to see the chain of actions and thoughts that the worker took, including any queries and tool uses. This can be helpful for observing what the agents are actually doing or debugging their behavior. ## Agent memory Each unique agent has its own "notebook" of memories. It can use this to remember things across execution runs. It will automatically use it to identify issues with queries, learn, and adapt to how your systems work. Sometimes it can be useful to encourage the agents to use their notebook more, particularly if you find they are repeatedly hitting an issue. Do this by chatting with the planner agent - tell it about the problem, and tell it to steer the executor agents to use their notebook more often. ## Integrations ## What are Integrations? Integrations are how Firetiger connects to your existing infrastructure, tools, and data sources. They serve two purposes: they **extend the capabilities** of your [Agents](./agents.txt) by granting them access to external tools, and they **provide data sources** that feed telemetry into Firetiger for analysis. You can manage your integrations at [/integrations]({{ site.ui_url }}/integrations). ## Connections Connections are integrations that give Firetiger ongoing access to an external service. When you set up a connection, you provide credentials and configuration, and Firetiger maintains the link on your behalf. Connections are used in two ways: - **As agent tools** — Agents can use connections to interact with external systems. For example, a [GitHub](../integrations/developer-tools/github.txt) connection lets agents read repositories and create issues, while a [Slack](../integrations/communications/slack.txt) connection lets them post messages to channels. - **As data sources** — Some connections pull data into Firetiger on an ongoing basis. A [PostgreSQL](../integrations/databases/postgres.txt) connection, for instance, lets agents query your database directly. For a full list of available connections, see the [Integrations](../integrations/) section of the docs. ## Ingest Sources Ingest sources are integrations that push telemetry data — logs, traces, and metrics — into Firetiger. These are typically configured on the sending side, pointed at your Firetiger ingest endpoint. You can see the health and latency of your active ingest sources at [/integrations/ingest]({{ site.ui_url }}/integrations/ingest): This page shows which sources are actively sending data, their recent latency, and any delivery issues. It's a good first place to check if you suspect telemetry isn't arriving. For setup guides on specific ingest sources, see the [Infrastructure](../integrations/infrastructure/) and [Observability](../integrations/observability/) integration docs. ## Credential Security When you configure an integration, any secret values — API keys, database passwords, OAuth tokens — are handled with care. They are **never visible to LLMs** and are **never stored at rest** outside of encrypted cloud secrets managers. Here's how it works: when an agent runs, its sandboxed environment receives dummy placeholder credentials. An isolated proxy sits between the sandbox and the external service. The proxy intercepts outgoing requests and rewrites the dummy credentials with the real values, which only it can access. The agent's LLM never sees or handles actual secrets — it only ever works with the placeholders. This means that even if an agent's behavior were compromised, the real credentials remain inaccessible to the model. ## Telemetry Firetiger ingests and stores telemetry data from your software systems. This is the data that [Agents](./agents.txt) use to understand what's happening in your infrastructure. We use the [OpenTelemetry](https://opentelemetry.io/) standard for data ingestion. OpenTelemetry defines three signal types: - **Logs** — textual records of events, like HTTP access logs, application errors, or audit trails. - **Traces** — records of request execution across services, showing the path a request takes and where time is spent. - **Metrics** — numeric measurements over time, like request rates, error counts, or CPU usage. You can send data from any OpenTelemetry-compatible source. See [Sending OpenTelemetry Data](../guides/opentelemetry.txt) for setup instructions, or browse [Integrations](../integrations/) for source-specific guides. ## How data is organized When Firetiger receives telemetry, it organizes it by **service name** and **time**. The service name comes from the OpenTelemetry `service.name` resource attribute. This is the standard way to identify which component of your system produced a piece of telemetry. If no `service.name` is set, data goes into a `default` table. Each distinct service name gets its own table. For example, if you have services named `api-gateway`, `billing-worker`, and `web-frontend`, your logs will be stored in three separate tables. This keeps queries fast — when an Agent investigates an issue with your billing system, it only needs to scan the `billing-worker` table, not your entire log volume. Service names are normalized when they're received: `api-gateway` becomes `api_gateway`, `MyService` becomes `my_service`, and so on. ## Structured logs The more structure your logs have, the more useful they are to Firetiger's agents. Plain text logs like `"user u_123 logged in"` work, but structured logs with typed fields are much better — they let agents write precise queries instead of parsing strings. A good structured log record uses OpenTelemetry attributes to capture discrete facts about an event. Here's what that looks like in practice: **An HTTP request log:** | Attribute | Value | | :--- | :--- | | `http.method` | `GET` | | `http.route` | `/api/v1/users` | | `http.status_code` | `200` | | `http.duration_ms` | `42` | | `user.id` | `u_123` | | `request.id` | `req_abc` | **A deployment event:** | Attribute | Value | | :--- | :--- | | `deploy.service` | `billing-worker` | | `deploy.sha` | `a1b2c3d` | | `deploy.environment` | `production` | | `deploy.trigger` | `merge` | **A background job completion:** | Attribute | Value | | :--- | :--- | | `job.name` | `sync_invoices` | | `job.duration_ms` | `12340` | | `job.status` | `success` | | `job.records_processed` | `847` | The key principle is: if you'd want to filter, group, or aggregate on a value, make it a separate attribute rather than embedding it in a message string. ### Sending structured logs with OpenTelemetry SDKs OpenTelemetry provides SDKs for most languages. Here are a few examples of emitting structured logs: **Python** ([opentelemetry-python](https://opentelemetry.io/docs/languages/python/)): ```python from opentelemetry._logs import SeverityNumber from opentelemetry.sdk._logs import LoggerProvider, LogRecord from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter provider = LoggerProvider() provider.add_log_record_processor( BatchLogRecordProcessor(OTLPLogExporter(endpoint="https://ingest.example.com/v1/logs")) ) logger = provider.get_logger("my-service") logger.emit(LogRecord( severity_number=SeverityNumber.INFO, body="invoice sync completed", attributes={ "job.name": "sync_invoices", "job.duration_ms": 12340, "job.status": "success", "job.records_processed": 847, }, )) ``` **Go** ([opentelemetry-go](https://opentelemetry.io/docs/languages/go/)): ```go import "go.opentelemetry.io/otel/log" logger := loggerProvider.Logger("my-service") record := log.Record{} record.SetBody(log.StringValue("invoice sync completed")) record.SetSeverity(log.SeverityInfo) record.AddAttributes( log.String("job.name", "sync_invoices"), log.Int("job.duration_ms", 12340), log.String("job.status", "success"), log.Int("job.records_processed", 847), ) logger.Emit(ctx, record) ``` **Node.js** ([opentelemetry-js](https://opentelemetry.io/docs/languages/js/)): ```javascript import { logs, SeverityNumber } from "@opentelemetry/api-logs" const logger = logs.getLogger("my-service") logger.emit({ severityNumber: SeverityNumber.INFO, body: "invoice sync completed", attributes: { "job.name": "sync_invoices", "job.duration_ms": 12340, "job.status": "success", "job.records_processed": 847, }, }) ``` See [Sending OpenTelemetry Data](../guides/opentelemetry.txt) for full setup instructions including configuring exporters and the `service.name` resource attribute. ## Schema inference When Firetiger receives log data, it automatically infers and evolves the schema of your tables based on the data it sees. You don't need to define schemas up front. If your application emits logs with structured attributes (like the examples above), Firetiger will detect the types and create typed columns for each one. `job.duration_ms` becomes an integer column, `job.status` becomes a string column, and so on. As new fields appear in your data, the schema expands to accommodate them. This also works for JSON bodies. If your logs contain a JSON string as the body, Firetiger will detect and unpack it into typed columns automatically. Attribute names are normalized to `snake_case` during ingestion — `invocationId` becomes `invocation_id`, `InstanceID` becomes `instance_id`, etc. ## Querying your data The primary way to query telemetry in Firetiger is through [Agents](./agents.txt). When an agent investigates an issue, it writes and executes SQL queries against your telemetry tables on your behalf. You describe what you're looking for in natural language, and the agent figures out the right tables, columns, and filters. You can also query your data directly as an [MCP](https://modelcontextprotocol.io/) client. This is useful for integrating Firetiger into coding agents, AI assistants, or any tool that speaks the MCP protocol. See [Using Firetiger with MCP](../guides/mcp-server.txt) for setup instructions. ## Volume and pricing Firetiger is built to accept very high volumes of telemetry data. We don't charge based on cardinality — you won't be penalized for having many unique label values, high-dimensional attributes, or a large number of distinct services. Send what you need, and query what matters. ## Deployments Firetiger tracks deployment events from your CI/CD systems. A deployment represents a specific Git commit being shipped to a specific environment — for example, commit `abc123` going live in `production`. You can view your deployment history at [/deployments]({{ site.ui_url }}/deployments). This shows each deployment event with its repository, environment, Git SHA, and status. Deployments are a building block for several Firetiger features: - [Deploy monitoring](../guides/deploy-monitoring.txt) — proactive, per-PR monitoring that activates when code goes live - [Post-deploy triggers](./agents.txt#post-deploy-triggers) — agent triggers that fire after a specific commit is deployed ## How deployments are registered There are two ways to register deployments with Firetiger. ### GitHub Deployments (automatic) If your CI/CD pipeline uses [GitHub Deployments](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments), Firetiger picks up deployment events automatically through your [GitHub integration](../integrations/developer-tools/github.txt). No extra configuration is needed once the connection is installed. This auto-creation can be disabled per-connection if your GitHub Deployment events don't map to meaningful production deploys (e.g., if you use them for CI build gates or preview environments). ### Deployment API (explicit) For other CI/CD systems, or when you want explicit programmatic control, you can register deployments directly via the API: ```bash curl -X POST {{ site.api_url }}/deployments \ -u "$FT_DEPLOY_USERNAME:$FT_DEPLOY_PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "repository": "owner/repo", "environment": "production", "sha": "abc123def456...", "deploy_time": "2025-01-15T10:00:00Z" }' ``` | Field | Required | Description | |---|---|---| | `repository` | yes | Repository in `owner/repo` format | | `environment` | yes | Deployment environment (e.g. `production`, `staging`) | | `sha` | yes | Git commit SHA that was deployed | | `deploy_time` | no | RFC 3339 timestamp; defaults to the time of the request | Deploy credentials are available on the [Deployments page]({{ site.ui_url }}/deployments#create) under the **Create a deployment** tab. ## What happens after a deployment Once a deployment is registered, Firetiger checks it against any active monitoring plans and post-deploy triggers using **Git ancestry**. ### Git ancestry matching Firetiger doesn't require the exact commit from a PR to be deployed. Instead, it checks whether the deployed commit is a *descendant* of the commit it's watching. This matters because in practice, the commit that actually gets deployed is rarely the exact merge commit of a single PR — it's usually a later commit that includes several merged PRs. For example, suppose you set up deploy monitoring on PR #42, which merges as commit `B`: ``` PR #42 │ A ── B ── C ── D ── E (main) │ │ merge of deployed PR #42 to prod ``` When commit `E` is deployed, Firetiger checks: is `B` an ancestor of `E`? It is — `E` contains all the changes from `B` — so the monitoring plan for PR #42 activates. This works regardless of how many other commits landed between `B` and `E`. ### Monitoring plans When a deployment's SHA is a descendant of a PR's merge commit, Firetiger marks that PR as deployed and begins running the monitoring plan that was set up for it. Checks run at 10 minutes, 30 minutes, 1 hour, 2 hours, 24 hours, and 72 hours after deploy. See [Monitoring your deploys](../guides/deploy-monitoring.txt) for the full guide on setting this up. ### Post-deploy triggers Post-deploy triggers use the same ancestry logic. Each trigger watches for a specific commit SHA (or any descendant of it) landing in a particular repository and environment. When a match is found, the trigger fires the associated agent after a configurable delay. See [Post-deploy triggers](./agents.txt#post-deploy-triggers) for details. ## Environments Firetiger doesn't prescribe a fixed set of environment names. Whatever string you pass as `environment` — whether that's `production`, `staging`, `us-east-1`, or `canary` — is used as-is. This means you can model your deployment topology however it actually works, without mapping it into a predefined set of stages. When a monitoring plan is tracking multiple environments, it handles them in a single pass. A new deployment to any environment resets the monitoring schedule for the entire plan, since a fresh deploy is a new risk event worth checking against all environments. ## Issues Issues describe recurring problems, errors, or system degradation that Firetiger has identified across your infrastructure. They're the output of Firetiger's triage pipeline — raw signals from [Agent](./agents.txt) investigations get filtered, deduplicated, and organized into a structured view of what's actually going wrong. You can see your issues at [/known-issues]({{ site.ui_url }}/known-issues). ## How issues get created Issues aren't created manually. When an Agent runs an investigation and discovers a problem, it reports what it found. A dedicated manager agent monitors these reports and decides what to do with each one: - If the problem matches an existing issue, the report is linked to it as a **mention**. - If the problem is new, the manager creates a new issue and assigns it an **expert** — a dedicated agent that owns that specific issue going forward. This means that by the time something appears as an issue, it's already been through a layer of LLM-driven triage. Duplicate reports get consolidated, and noise gets filtered out. ## Issue status Each issue has one of three statuses: - **Active** — the problem is ongoing and hasn't been resolved. - **Resolved** — the problem has been verified as fixed. The expert agent requires evidence before marking an issue resolved, typically from a follow-up investigation confirming the errors or degradation have stopped. - **Muted** — the issue is acknowledged but deprioritized. Use this for known problems you're choosing not to fix right now, or expected behavior that doesn't need attention. ## The issues list The issues list at [/known-issues]({{ site.ui_url }}/known-issues) shows all your issues, filterable by status. On the right side is a chat with the **manager agent**. This agent understands all your current issues and can help you reason about what's happening across your systems. Things you can ask the manager: - "What's going on with the database right now?" - "Are any of these issues related to each other?" - "Create a new issue for the payment timeouts we've been seeing." - "Should we merge these two issues?" The manager can also kick off new investigations on your behalf if it needs more data to answer a question. ## Issue details Clicking into an issue shows its detail page. The key fields are: - **Summary** — a concise description of the problem, what's known about it, and recommended actions. This is written for humans. - **Mentions** — links back to the individual investigation sessions that reported this problem. Each mention is a trail to when and how the issue was discovered. As new reports come in that match this issue, they're added here automatically. - **Links** — external references like GitHub PRs, Linear tickets, Slack threads, or any other URL relevant to the issue. The detail page also has a collapsible "Investigation Details" section. This is the expert agent's internal working memory — it's useful for understanding the agent's reasoning, but it's written in the agent's own style rather than polished for human reading. ## The expert agent Each issue has its own expert agent, accessible via the chat panel on the right side of the detail page. The expert owns that specific issue and is responsible for driving it to resolution. The expert works by delegating to investigation sessions linked to the issue. It can ask them to gather specific data, verify fixes, or check whether error patterns are still occurring. It maintains a structured memory of what's been investigated and what's been verified. Things you can ask an expert: - "What's the root cause?" - "Is this still happening? We deployed a fix at 2pm." - "Who is affected by this?" - "Link this to our runbook." - "Mark this as resolved." The expert will push back if you ask it to resolve an issue without evidence — it needs to see that the problem has actually stopped before it'll close things out. ## Notifications By default, issues don't notify anyone. To set up notifications, go to [/known-issues/notifications]({{ site.ui_url }}/known-issues/notifications). The notifications page has a chat interface where you describe your notification policy conversationally. You tell it which [connections](../integrations/) should receive notifications — for example, a Slack connection — and which channels to use. The planner agent takes care of configuring the routing rules. Without a notification policy, the only way to learn about issues is by checking the issues list directly. ## Knowledge Knowledge is Firetiger's accumulated understanding of your systems. As agents investigate, query, and interact with your infrastructure, they build up a structured body of knowledge that makes every subsequent interaction smarter. This knowledge is shared across all agents in your organization. You don't need to seed knowledge manually — it's built automatically from your telemetry. But you can supplement it with human-authored context via [Firetiger.md](#firetigermd). ## Services A service represents a component in your system — an API server, a background worker, a database, a message queue. You can browse your discovered services at [/knowledge/services]({{ site.ui_url }}/knowledge/services). Firetiger discovers services from your telemetry and maintains a profile of each one, including: - A description of what the service does and how it fits into your architecture - The telemetry patterns it emits — log attributes, metric names, trace spans - Correlation IDs used to track requests through or across the service (e.g., `request_id`, `trace_id`, `batch_id`) - Dependencies on other services - Known error patterns and expected anomalies (so agents don't raise false alarms on, say, expected timeout errors) - Tags for environment, region, version, and other metadata When an agent investigates an issue, it uses service definitions to understand the architecture around the problem — what services are involved, how they communicate, and what telemetry to look for. ## Flows A flow describes an end-to-end process that spans multiple services — something like "user authentication," "order processing," or "data ingestion pipeline." You can browse your flows at [/knowledge/flows]({{ site.ui_url }}/knowledge/flows). Where services describe individual components, flows describe how those components work together to accomplish something. Each flow contains: - A set of **key identifiers** — the correlation IDs that tie telemetry together across the flow (e.g., `user_id`, `order_id`, `session_id`) - A sequence of **steps**, each documenting which services are involved, what telemetry signals to expect, and how to query for the relevant data - **Operational notes** — deployment quirks, timing variations, seasonal behaviors, and other real-world context Flows are what let agents reason about cross-service behavior. When investigating a latency spike in your checkout process, an agent can look up the "checkout" flow to find the services involved, the correlation IDs to thread through, and example queries that have been useful in the past. Firetiger maintains a curated set of flows (typically a few dozen) and actively consolidates or removes stale ones to keep the set focused and useful. ## Customers If your system serves multiple customers or tenants, Firetiger can track them as first-class knowledge. You can browse your customers at [/knowledge/customers]({{ site.ui_url }}/knowledge/customers). A customer profile includes: - How to identify the customer in telemetry — which fields, which tables, what extraction patterns - A workload summary describing the customer's usage patterns and volume - An operational runbook with customer-specific investigation guidance This lets agents quickly scope queries to a specific customer when investigating issues, and understand whether a customer's behavior is normal for them. ## Notes Notes are Firetiger's general-purpose memory, organized by domain. You can browse them at [/knowledge/notes]({{ site.ui_url }}/knowledge/notes). They accumulate insights that don't fit neatly into services, flows, or customer profiles — things like common debugging techniques, system-wide operational patterns, or recurring themes across investigations. Notes are the primary way knowledge persists between agent sessions. When an agent discovers something useful during an investigation, it records the finding. Background agents periodically review these findings and incorporate the durable ones into the shared notes. ## Known Issues Known issues are documented problems that Firetiger is tracking. Each has a title, detailed context, and a status: **active**, **resolved**, or **muted**. They can be linked to specific services, objectives, and external tickets. When an investigation detects a pattern matching a known issue, the agent can reference it rather than re-diagnosing from scratch. When an issue is resolved, agents verify the fix by checking telemetry for evidence that the problem has stopped. See [Issues](./issues.txt) for more detail. ## How knowledge is built Firetiger runs a set of background researcher agents that periodically discover and maintain knowledge. These don't count against your agent usage. - A **service researcher** investigates telemetry to discover and document services, their dependencies, and their telemetry patterns - A **flow researcher** discovers end-to-end processes and maintains the curated set of flows - A **customer researcher** identifies top customers and their workload characteristics - A **synthesis agent** reviews all recent agent sessions to extract durable insights — user corrections, consensus patterns across multiple investigations, and repeated mistakes that indicate a knowledge gap Knowledge also grows organically during regular investigations. When an agent discovers something new about your systems, it records the finding. The synthesis agent picks it up on its next pass and incorporates it into the shared knowledge base. User corrections always take precedence over automatically discovered patterns. If you correct an agent during an investigation — "that's not an error, those timeout logs are expected" — that correction is preserved and propagated so no agent makes the same mistake again. ## Firetiger.md Firetiger.md is a human-authored markdown document where you can provide foundational context about your organization that doesn't need to be discovered from telemetry. Every agent reads it at the start of every session. This is a good place to put things like: - What your company does ("We're an authentication provider") - High-level architecture ("We run three main services: API, Worker, and Scheduler") - Business context ("Our peak traffic is during US business hours") - Naming conventions ("We call our internal customers 'tenants'") - Operational preferences ("Always check the audit log before escalating access issues") You can edit Firetiger.md at [/knowledge/firetiger]({{ site.ui_url }}/knowledge/firetiger). It's intentionally simple — just a markdown file — so it's easy to keep up to date. ## Knowledge and privacy Knowledge is scoped to your organization. It's never shared across organizations, and agents in one organization cannot see another organization's knowledge. Automatically discovered knowledge is derived solely from your own telemetry and agent interactions. Human-authored content in Firetiger.md and user corrections during investigations are marked as such and given priority over automatic discoveries, so they're never silently overwritten by an agent. --- # Guides Step-by-step guides for setting up and using Firetiger. ## OpenTelemetry Integration # How to Send OpenTelemetry to Firetiger This guide will walk you through configuring your application to export OpenTelemetry-compliant logs, metrics, and traces to Firetiger. ## Prerequisites Before you begin, ensure you have: - An active Firetiger deployment - An application that you want to monitor - OpenTelemetry instrumentation set up in your application ## Step 1: Get your Firetiger ingest credentials 1. Log in to your Firetiger account 2. Navigate to the **Integrations** page 3. Find your **Ingest Basic Auth Credentials** 4. **Important**: Copy these credentials securely - you'll need them to authenticate your telemetry exports Your credentials will include: - **Deployment Name**: Your unique Firetiger deployment identifier - **Password**: Your ingest authentication password - **Endpoint**: Your Firetiger OTLP endpoint (typically `{{ site.ingest_url | remove: "https://" }}:443`) You can find these credentials on the Firetiger Settings page: `{{ site.ui_url }}/settings` ## Step 2: Configure your OpenTelemetry collector or SDK Firetiger accepts OpenTelemetry data via the OTLP or HTTP protocol. You can send data directly from your application using OpenTelemetry SDKs, or route it through an OpenTelemetry Collector. ### Option A: Using the OpenTelemetry Collector Create or update your `config.yaml` file: ```yaml receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" http: endpoint: "0.0.0.0:4318" processors: batch: exporters: otlphttp/firetiger: endpoint: {{ site.ingest_url }}:443 tls: insecure: false headers: "Authorization": "Basic " service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/firetiger] logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/firetiger] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/firetiger] ``` **To create your Base64-encoded credentials:** ```bash echo -n "{{ site.deployment_name }}:{password}" | base64 ``` ### Option B: Direct from your application Configure your OpenTelemetry SDK to export directly to Firetiger: **Python example:** ```python from opentelemetry import trace from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor import base64 # Create base64-encoded credentials deployment_name = "{{ site.deployment_name }}" password = "{password}" auth = base64.b64encode(f"{% raw %}{deployment_name}:{password}{% endraw %}".encode()).decode() # Configure the exporter exporter = OTLPSpanExporter( endpoint="{{ site.ingest_url }}:443/v1/traces", headers={"Authorization": f"Basic {auth}"} ) # Set up the tracer provider = TracerProvider() provider.add_span_processor(BatchSpanProcessor(exporter)) trace.set_tracer_provider(provider) ``` **Node.js example:** ```jsx const { NodeSDK } = require("@opentelemetry/sdk-node"); const { OTLPTraceExporter, } = require("@opentelemetry/exporter-trace-otlp-http"); const deploymentName = "{{ site.deployment_name }}"; const password = "{password}"; const auth = Buffer.from(`{% raw %}${deploymentName}:${password}{% endraw %}`).toString("base64"); const traceExporter = new OTLPTraceExporter({ url: "{{ site.ingest_url }}:443/v1/traces", headers: { Authorization: `Basic ${auth}`, }, }); const sdk = new NodeSDK({ traceExporter, }); sdk.start(); ``` ## Step 3: Deploy and verify After configuring your telemetry export: 1. Deploy your updated application or collector configuration 2. Generate some traffic to your application 3. Log in to your Firetiger account and navigate to your traces or logs view 4. You should see telemetry data flowing in within a few moments ## Troubleshooting **No data appearing in Firetiger?** - Verify your credentials are correct (deployment name and password) - Check that your endpoint URL matches the format: `{{ site.ingest_url | remove: "https://" }}:443` - Ensure your Base64-encoded credentials are formatted correctly - Check your application or collector logs for connection errors - Verify that your application is generating telemetry data **Authentication errors?** - Double-check your credentials from the Integrations page - Ensure there are no extra spaces or characters in your Base64-encoded string - Verify the Authorization header format: `Basic ` ## Additional resources - [OpenTelemetry Documentation](https://opentelemetry.io/docs/) - [Configure the OpenTelemetry Collector](https://www.notion.so/Configure-the-OpenTelemetry-Collector-19070c7133b480d4a4fdc4c18960d2d3?pvs=21) For more help, contact Firetiger support or check our documentation. ## MCP Server # Firetiger MCP Server Firetiger exposes an MCP (Model Context Protocol) server that allows AI assistants like Claude, Cursor, and other MCP-compatible clients to interact with your Firetiger data. The server uses HTTP streaming transport and authenticates via OAuth with your normal Firetiger credentials. When you first connect from an MCP client, you'll be redirected to sign in. **Quick start:** Visit your deployment's setup page at `/mcp` (e.g., `{{ site.ui_url }}/mcp`) for copy-pastable setup commands. ## Endpoint Your MCP endpoint is: ``` {{ site.api_url }}/mcp/v1 ``` ## Client Configuration ### Claude Desktop Add to your Claude Desktop configuration file (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS): ```json {% raw %}{ "mcpServers": { "firetiger": { "url": "{% endraw %}{{ site.api_url }}/mcp/v1{% raw %}" } } }{% endraw %} ``` ### Cursor In Cursor settings, add the MCP server configuration: ```json {% raw %}{ "mcpServers": { "firetiger": { "url": "{% endraw %}{{ site.api_url }}/mcp/v1{% raw %}" } } }{% endraw %} ``` ### Claude Code Add the Firetiger MCP server using the CLI: ```bash claude mcp add firetiger --transport http {{ site.api_url }}/mcp/v1 ``` Then authenticate by running `/mcp` in Claude Code and following the prompts. ## Available Tools ### Resource Tools The MCP server exposes generic CRUD tools that work across all resource collections. Use `schema` to discover fields and types before creating or updating resources. | Tool | Description | |------|-------------| | `list` | List resources in a collection. Supports filtering, ordering, and pagination. | | `get` | Get full details of a specific resource by name. | | `schema` | Get the schema for a collection — field names, types, required/optional, enum values. | | `create` | Create a new resource in a collection. | | `update` | Partially update an existing resource. Only fields included in the request body are modified. | | `delete` | Soft-delete a resource by name. | ### Resource Collections | Collection | Operations | Description | |------------|-----------|-------------| | `known-issues` | List, Get, Create, Update, Delete | Track recurring problems for automatic correlation with future incidents | | `notes` | List, Get, Create, Update, Delete | Knowledge base entries and documentation | | `connections` | List, Get, Create, Update, Delete | External service connections (Postgres, HTTP, etc.) | | `customers` | List, Get, Create, Update, Delete | Customer records and metadata | | `investigations` | List, Get, Create, Update | Automated investigation runs | | `runbooks` | List, Get, Create, Update, Delete | Operational runbooks | | `triggers` | List, Get, Create, Update, Delete | Alert and automation triggers | | `scheduled-agent-runs` | List, Get, Create, Update, Delete | Scheduled recurring agent tasks | | `agents` | List, Get, Create, Update, Delete | Agent configurations | | `sessions` | List, Get, Create, Delete | Agent sessions (nested under agents) | | `issue-notification-policies` | List, Get, Update | Notification policy configuration (singleton) | ### Agent Tools | Tool | Description | |------|-------------| | `send_agent_message` | Send a message to an agent session and wait for a response. | | `read_agent_messages` | Read the message history from an agent session. | ### Query Tool | Tool | Description | |------|-------------| | `query` | Execute DuckDB SQL against Firetiger's Iceberg data warehouse. Supports standard SQL including JOINs, CTEs, and aggregate functions. | ### Credentials Tool | Tool | Description | |------|-------------| | `get_ingest_credentials` | Get OTLP ingest endpoint URL and authentication credentials. | ### Onboarding Tools These tools appear only when the corresponding integration hasn't been connected yet. Once you connect a provider, its onboarding tool is automatically hidden. | Tool | Description | |------|-------------| | `onboard_github` | Connect your GitHub account. Returns an authorization URL to open in your browser. | | `onboard_slack` | Connect your Slack workspace. Returns an authorization URL to open in your browser. | | `onboard_linear` | Connect your Linear workspace. Returns an authorization URL to open in your browser. | ## Example Workflows ### Investigate issues Ask Claude to query your logs and investigate problems: > "Figure out the reason the api server is crash looping in staging" Claude will query your logs, analyze error patterns, and identify the root cause. ### Fix a known issue Ask Claude to work on a known issue tracked in Firetiger: > "Get the known issue 'memory leak in worker pool', verify it's still happening, find the root cause, and fix it" Claude will fetch the issue details, query recent logs and metrics to confirm the problem, analyze the patterns, and implement a fix. ### Create and manage resources Ask Claude to create or update Firetiger resources directly: > "Create a known issue for the Redis connection timeouts we've been seeing under high load" Claude will call `schema` to learn the fields, then `create` to make the known issue. > "Resolve the Redis timeout known issue and add a note explaining the fix" Claude will `update` the known issue status and `create` a note with the details. ### Set up telemetry integration The `integrate-firetiger` prompt provides a step-by-step guide for adding OpenTelemetry instrumentation to send data to Firetiger. It walks through fetching credentials, exploring your codebase, installing the SDK, and configuring the exporter. In Claude Code, invoke it with the slash command: ``` /firetiger:integrate-firetiger ``` Or ask Claude directly: > "Help me integrate OpenTelemetry into this project to send data to Firetiger" ## Related Documentation - [MCP Server Connections](../integrations/custom/mcp.txt) - Connect Firetiger to external MCP servers - [OpenTelemetry Integration](./opentelemetry.txt) - Send telemetry data to Firetiger ## Agent Webhooks # Running Agents With Webhooks Every Firetiger agent has a **manual trigger** with a stable **webhook URL**. Posting to that URL fires the trigger — the HTTP body and headers become the agent's opening message. This lets you kick off an agent run from a CI pipeline, an alerting system like PagerDuty or incident.io, a cron job, or any other tool that can make an HTTP request. No API key is required. The opaque token in the URL is the credential; treat it as a secret. ## Finding the Webhook URL Open the agent's detail page in the Firetiger UI and look at the **Triggers** section. You'll see a **Webhook URL** with a copy button — something like: ``` {{ site.api_url }}/webhooks/dGhpc0lzQVRlc3RUb2tlbjEyMzQ1Njc4OTA ``` Copy that URL; you'll use it directly in your HTTP request. ## Making the Request Invoking a webhook trigger is a single POST to the webhook URL. The body can be any format — Firetiger passes it through to the agent as-is. ```bash curl -X POST \ {{ site.api_url }}/webhooks/dGhpc0lzQVRlc3RUb2tlbjEyMzQ1Njc4OTA \ -H "Content-Type: application/json" \ -d '{ "event": "incident.triggered", "incident": {"id": "Q1A2B3C4", "title": "High error rate on checkout"} }' ``` The agent receives a structured message containing the timestamp, request headers, and body. A few headers are omitted (like `X-Forwarded-For`). The body is included as-is, truncated to 50 kB if larger. No `Content-Type` requirement — the body is passed through verbatim. Including `Content-Type` is recommended so the agent knows how to interpret the payload. ## Response A successful invocation returns the created session name: ```json { "session": "agents/uvxtwa1yoyrx/sessions/sess456" } ``` The `session` field is the name of the agent session that was started. You can use it to poll for results or read the agent's output via the agent sessions API. ## Using Multiple Sources With One Trigger You can multiplex multiple webhook sources to the same trigger by including a custom header (e.g., `X-Alert-Team: platform`). The agent receives all headers and can use them for routing or interpretation without requiring a separate trigger per source. ## BigQuery Integration # Query Firetiger with BigQuery > **Note:** Customers whose Firetiger deployment lives on GCP already have BigQuery configured. This guide is for Firetiger on AWS only. Firetiger Iceberg tables can be queried directly from BigQuery without ETL. This process requires frequent updates, as Google hasn't added support for external Iceberg REST catalog services. In our example, a typical workstation environment is assumed; production deployments will be different. ## Credentials Establish both AWS and GCP credentials. The `firetiger` command uses the common SDKs to do this. For GCP, run a command like `gcloud auth login --update-adc`. Learn more: [Set up Application Default Credentials](https://docs.cloud.google.com/docs/authentication/provide-credentials-adc). For AWS, we've run a command like `aws sso login`. Learn more: [Authentication and access using AWS SKDs and tools](https://docs.aws.amazon.com/sdkref/latest/guide/access.txt). ## GCP Configuration Use this information to configure the example env vars `GOOGLE_CLOUD_PROJECT`, `FT_BIGQUERY_LOCATION`, `FT_BIGQUERY_CONNECTION`. Identify the GCP project where BigQuery lives. Specifically, a "PROJECT_ID" found in the left column returned by `gcloud projects list`. Identify the BigQuery location, which is similar to a region. Specifically, a "region name" matching your Firetiger AWS region in [the list of "BigQuery Omni locations"](https://docs.cloud.google.com/bigquery/docs/locations#omni-loc). Create a BigQuery Connection in the GCP web console. Navigate to the [BigQuery Studio](https://console.cloud.google.com/bigquery). Under the "Explorer" tab (the icon looks like a compass), click "Connections", then "Create connection". - Connection type: "Vertex AI remote models..." - Connection ID: You decide, something like `firetiger` is fine. - Location type: "Multi-region" - Multi-region: Whichever option matches the BigQuery location from earlier. ## AWS Configuration Use this information to configure the example env vars `AWS_PROFILE`, `FT_CATALOG`, `FT_NAMESPACE`. Identify the AWS profile. Specifically, one of the alternatives returned by `aws configure list-profiles`. Identify the Iceberg catalog URI. If you don't know, then use `glue://`. Identify the Iceberg namespace where your Firetiger tables live. This is the Firetiger "deployment name" provided by Firetiger (e.g., `{{ site.deployment_name }}`). ## Other Configuration `FT_MAX_CONCURRENCY` limits table sync concurrency For example, `10` allows 10 tables to be synced concurrently. `FT_TIMEOUT` causes the process to exit after this duration. The value is a [Golang `time.Duration` strings](https://pkg.go.dev/time#ParseDuration), such as `30s` or `5m`. `OTEL_*_EXPORTER` are OpenTelemetry SDK environment variables. Learn more: [SDK Environment Variables](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection) `FT_LOG_LEVEL` is a [Golang `slog`](https://pkg.go.dev/log/slog) level, one of `ERROR`, `WARN`, `INFO`, `DEBUG`. ```bash docker run \ --rm \ --name firetiger-bigquery-sync \ -v $HOME/.config/gcloud/application_default_credentials.json:/root/.config/gcloud/application_default_credentials.json \ -v $HOME/.aws/:/root/.aws \ -e GOOGLE_CLOUD_PROJECT="$GOOGLE_CLOUD_PROJECT" \ -e FT_BIGQUERY_LOCATION="$FT_BIGQUERY_LOCATION" \ -e FT_BIGQUERY_CONNECTION="$FT_BIGQUERY_CONNECTION" \ -e AWS_PROFILE="$AWS_PROFILE" \ -e FT_CATALOG="$FT_CATALOG" \ -e FT_NAMESPACE="$FT_NAMESPACE" \ -e FT_MAX_CONCURRENCY=10 \ -e FT_TIMEOUT=1m \ -e OTEL_LOGS_EXPORTER=none \ -e OTEL_METRICS_EXPORTER=none \ -e OTEL_TRACES_EXPORTER=none \ -e FT_LOG_LEVEL="INFO" \ 975050257559.dkr.ecr.us-west-2.amazonaws.com/firetiger/firetiger \ gcp bigquery sync ``` ## incident.io Workflows # Triggering Agents from incident.io Workflows You can configure an incident.io workflow to call a Firetiger agent automatically when an incident is created (or at any other workflow trigger point). The agent receives details about the incident as its opening prompt, so it can immediately start investigating, pulling relevant logs, or running a runbook. ## Prerequisites You'll need the **webhook URL** for the agent you want to invoke. Open the agent in Firetiger, look at the **Triggers** section, and copy the **Webhook URL**. It'll look like `{{ site.api_url }}/webhooks/dGhpc0lzQVRlc3RUb2tlbjEyMzQ1Njc4OTA`. See [Agent Webhooks](agent-webhooks.txt) for more detail on how webhook invocation works. You'll also need a Firetiger API key to authenticate the request. See [API Keys](../account-management/api_keys.txt) for instructions on creating one. ## Creating the Workflow In incident.io, go to **Workflows** and create a new workflow. Set the trigger to **Incident created** (or whichever lifecycle event you want to fire on). Add a **Send a webhook** step and fill it in as follows. ### URL Paste the webhook URL you copied from the Firetiger UI: ``` {{ site.api_url }}/webhooks/dGhpc0lzQVRlc3RUb2tlbjEyMzQ1Njc4OTA ``` ### Method `POST` ### Headers | Key | Value | |-----|-------| | `Authorization` | `Bearer {your-api-key}` | ### Body The body is passed through to the agent as-is. Use incident.io's template syntax (`{% raw %}{{variable}}{% endraw %}`) to include incident details so the agent has context to work with. ```json { "event": "incident.created", "incident_id": "{% raw %}{{incident.id}}{% endraw %}", "incident_name": "{% raw %}{{incident.name}}{% endraw %}", "message": "Investigate this incident. Check for relevant errors, anomalies, or spikes in the data from around the time it was declared." } ``` The agent receives the full body alongside the request headers, so include whatever context is useful. The more detail you provide, the better the agent can orient itself. ## What Happens Next When the workflow fires, Firetiger creates a new agent session and returns a session ID. The agent starts working immediately on the webhook payload. You can see the session on the agent's page in the Firetiger UI, or poll the sessions API to read its output. ## Related Documentation - [Agent Webhooks](agent-webhooks.txt) — Full reference for webhook trigger URLs ## Monitoring your deploys Firetiger can monitor your deployments proactively, developing sophisticated, targeted alarms and metrics on a per-PR basis. This is a powerful tool for building confidence in the changes you are rolling out. You can quickly detect whether your change broke stuff, but also whether it is accomplishing it's intended changes. At Firetiger, we use this to ship faster. We use lots of agentic coding tools to write code, fix bugs, and build features. While automated testing is important, it's not the complete story; often the details of how things run in production can complicate things, so we were doing a lot of manual verification. With Firetiger's deploy monitoring suite, you can keep moving forwad, knowing that an agent is automatically verifying that a PR's changes are having their intended effect. ## Prerequisites To use deploy monitoring, you'll need to: - Install the [GitHub Connection](../integrations/developer-tools/github.txt) - Register deployments with Firetiger — either via [GitHub Deployments](#registering-deployments-via-github) (automatic) or the [explicit deployment API](#registering-deployments-via-the-api) (for other CI/CD systems) ## Registering deployments via GitHub If your CI/CD pipeline uses [GitHub Deployments](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments), Firetiger picks up deployment events automatically through the GitHub Connection webhook. No extra configuration is needed once the connection is installed. ## Registering deployments via the API If you use a different CI/CD system, or want explicit programmatic control (scripted promotions, post-hoc registration, etc.), you can register deployments directly: ```bash curl -X POST {{ site.api_url }}/deployments \ -u "$FT_DEPLOY_USERNAME:$FT_DEPLOY_PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "repository": "owner/repo", "environment": "production", "sha": "abc123def456...", "deploy_time": "2024-01-15T10:00:00Z" }' ``` **Fields:** | Field | Required | Description | |---|---|---| | `repository` | yes | Repository in `owner/repo` format | | `environment` | yes | Deployment environment (e.g. `production`, `staging`) | | `sha` | yes | Git commit SHA that was deployed | | `deploy_time` | no | RFC 3339 timestamp of when the deploy occurred; defaults to the time of the request | **Auth:** Use your deploy credentials (Basic auth). Find them in the Firetiger UI on the [Deployments page]({{ site.ui_url }}/deployments#create) under the **Create a deployment** tab. **Response:** `200 OK` with a JSON body containing the created deployment's resource name: ```json {"name": "deployments/abc123"} ``` ## Enabling monitoring for a PR To instruct Firetiger to monitor changes in a PR, just tag it (as "`@firetiger`") in a comment on the PR: You can include extra detail if you like, as in the above example; this will be passed as helpful context to Firetiger as it figures out what to focus on. You should very quickly get an "👀" response on your comment, which shows that the GitHub Connection is correctly installed so we can hear your message. You'll then see a response from Firetiger: You can click on the embedded link to follow along and see Firetiger's agent develop a targeted plan. This plan will incorporate research from the Pull Request metadata, code changes, other code in the repo, Git history, and system research collected by Firetiger's other agents. Once a plan is fully developed and ready to execute, you'll get a summary of it presented as another PR comment: ## Once monitoring is set up Once the PR is merged, we mark the monitoring plan as "ready", and we'll check for its presence in deployments. When a deployment is registered — either through GitHub or the explicit API — Firetiger will compare its Git SHA with that of the PR's merge. If the PR is an ancestor of the deployment, then we'll mark the PR as deployed, and start actively monitoring, following the plan that was developed. After a deploy, checks run at 10 minutes, 30 minutes, 1 hour, 2 hours, 24 hours, and 72 hours. Each check examines both intended effects and unintended issues. If a new environment deploys the same PR, the schedule resets to cover the fresh deployment. You'll receive updates on the status of the monitoring on the Pull Request directly, including an update when intended effects have been observed: ## When things go wrong If monitoring detects issues, it will quickly notify you on the Pull Request where the monitoring was set up. You'll get a message with detailed explanation of what was found that was out of expectations. In addition, it will create Known Issues in your Firetiger project. These can be fed into Claude Code through the [MCP integration](./mcp-server.md) to be quickly resolved, and will be published to Firetiger's internal knowledge store so. You can also configure Firetiger to alert you on Slack when known issues are created or updated. ## Connect to a Private Database with Tailscale # Connect Firetiger to Your Private Network Using Tailscale This guide walks through connecting Firetiger to an AWS RDS PostgreSQL database that is not publicly accessible, using Tailscale as the network transport. By the end, Firetiger agents will be able to query your private RDS instance through a secure Tailscale tunnel. ## Prerequisites - A [Tailscale](https://tailscale.com) account with admin access - Your RDS database must be reachable from your tailnet (via a [subnet router](https://tailscale.com/kb/1019/subnets) in the same VPC) ## Step 1: Configure Tailscale ACLs Open the [Access Controls](https://login.tailscale.com/admin/acls) page in the Tailscale admin console. Add a `tag:firetiger` tag and grant it access to your database port: ```json "tagOwners": { "tag:firetiger": ["autogroup:admin"] }, "grants": [ { "src": ["tag:firetiger"], "dst": ["*"], "ip": ["5432"] } ] ``` > Restrict `dst` to specific machines or tags for tighter security (e.g., `["tag:databases"]` instead of `["*"]`). ## Step 2: Create a Tailscale OAuth Client 1. Go to [Settings > OAuth clients](https://login.tailscale.com/admin/settings/oauth) 2. Click **Generate OAuth client** 3. Set the description to something like `firetiger` 4. Under **Tags**, select `tag:firetiger` 5. Under **Scopes**, ensure `auth_keys` Write is included (this allows the client to generate auth keys with the selected tags) 6. Click **Generate** 7. Copy the **Client ID** and **Client Secret** > The client secret is only shown once. Save it securely before closing the dialog. > The OAuth client must have the `tag:firetiger` tag selected. Without it, the proxy cannot generate tagged auth keys and will fail with "requested tags are invalid or not permitted". ## Step 3: Find Your Tailnet Name You'll need your tailnet name for the next step. Find it at [Settings > General](https://login.tailscale.com/admin/settings/general), or run: ```bash tailscale status --json | jq -r .MagicDNSSuffix ``` It looks like `example.ts.net` or `tail1234.ts.net`. ## Step 4: Create the Network Transport 1. Navigate to <{{ site.ui_url }}/integrations/network-transports> 2. Click **Create Network Transport** > **Tailscale** 3. Enter a display name (e.g., "Tailscale") 4. Enter your Tailscale OAuth Client ID and Client Secret from Step 2 5. Enter your tailnet name from Step 3 6. Optionally set a hostname for the proxy node (default: auto-generated) 7. Click **Create Network Transport** ## Step 5: Create the Database Connection 1. Navigate to <{{ site.ui_url }}/integrations/connections/new> 2. Select **PostgreSQL** 3. Enter the connection details: - **Host**: Use the **private IP or DNS name** of your RDS instance (the one reachable from within the VPC, not a public endpoint — e.g., `mydb.abc123.us-east-1.rds.amazonaws.com`) - **Port**: `5432` - **Database**: your database name - **Username / Password**: your database credentials - **SSL Mode**: `require` - **Read Only**: enabled (recommended for production) 4. Under **Network Transport**, select your Tailscale network transport 5. Click **Save** ## Step 6: Test the Connection On the connection page, click **Save + Test**. If successful, agents can now query your private RDS database through the Tailscale tunnel. ## Troubleshooting | Error | Cause | Fix | | --------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------- | | "requested tags are invalid or not permitted" | OAuth client doesn't have `tag:firetiger` | Recreate the OAuth client with the tag selected | | "tailnet not found" | Wrong tailnet name | Check `tailscale status --json \| jq -r .MagicDNSSuffix` | | "tailnet-owned auth key must have tags set" | Network transport missing `tags` field | Update the transport to include `"tags": ["tag:firetiger"]` | | Connection times out | Database not reachable from tailnet | Verify your subnet router is running and the RDS security group allows traffic from the subnet router | ## How It Works ``` Agent ──► Firetiger Proxy ──► Tailscale Tunnel ──► Subnet Router ──► RDS (ephemeral (in your node with VPC) tag:firetiger) ``` The proxy joins your tailnet as an ephemeral node, dials the RDS endpoint through the Tailscale mesh network, and forwards the database traffic. The node is automatically removed when the connection closes. ## Related Documentation - [Network Transports](/integrations/networking/network-transports.txt) — Overview of network transports - [Tailscale Transport Reference](/integrations/networking/tailscale.txt) — Full configuration reference - [PostgreSQL Connections](/integrations/databases/postgres.txt) — PostgreSQL connection parameters - [AWS VPC Peering](/integrations/networking/aws-vpc-peering.txt) — Alternative: direct VPC peering for BYOC deployments --- # Integrations Connect Firetiger to your existing tools and infrastructure. ## Categories - **[Databases](databases/)** — PostgreSQL, MySQL, ClickHouse - **[Infrastructure](infrastructure/)** — AWS, GCP, Cloudflare, CloudFront - **[Developer Tools](developer-tools/)** — GitHub, incident.io, Pylon - **[Communications](communications/)** — Slack, SendGrid, Google Postmaster - **[Observability](observability/)** — Vector, Datadog - **[Custom](custom/)** — HTTP APIs, MCP servers ## Databases Connect Firetiger agents to your databases for querying and analysis. ### PostgreSQL Connections PostgreSQL connections enable agents to query relational databases. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Network Configuration Firetiger's query servers must be able to reach your database. Choose the appropriate networking setup based on your database configuration: ### 1. Private Network Database **Scenario**: Database runs in a private VPC/network (AWS, GCP, Azure) **Solution**: Set up a private network connection: - **AWS**: Configure AWS PrivateLink - **GCP**: Configure Private Service Connect - **Azure**: Configure Private Link Contact Firetiger support to coordinate private network setup. ### 2. Public Database with IP Allowlist **Scenario**: Database accepts public connections but restricts access by IP address **Solution**: Add Firetiger's static IP addresses to your database's allowlist - Contact Firetiger support to obtain the static IP addresses for your deployment's query servers - Add these IPs to your database firewall rules or security groups ### 3. Public Database with Standard Authentication **Scenario**: Database accepts public connections with username/password authentication **Solution**: No special networking configuration needed - Ensure your database accepts connections on the standard PostgreSQL port (5432) - Verify firewall allows inbound connections from the internet - Use `ssl_mode: "verify-full"` for secure connections ## Connection Parameters A PostgreSQL connection requires the following configuration: ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `host` | string | Database hostname or IP address (e.g., `db.example.com`) | | `port` | int32 | Database port number (typically `5432`) | | `database` | string | Name of the database to connect to | | `username` | string | Username for authentication | | `password` | string | Password for authentication (stored securely as a secret) | ### Optional Parameters | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `ssl_mode` | string | SSL/TLS connection mode (see below) | `require` | | `role` | string | PostgreSQL role to assume after connecting | None | | `read_only` | bool | Enable database-level read-only enforcement | `false` | ## SSL Modes The `ssl_mode` parameter controls how the connection encrypts data in transit. Choose the appropriate mode based on your security requirements: | Mode | Description | Use When | |------|-------------|----------| | `disable` | No SSL encryption | **Not recommended** - Only for local development or testing | | `require` | Require SSL but don't verify server certificate | You want encryption but certificate verification isn't critical | | `verify-ca` | Require SSL and verify the server certificate is signed by a trusted CA | You have a proper CA-signed certificate | | `verify-full` | Require SSL, verify certificate, and check hostname matches | **Most secure** - Recommended for production | For production environments, use `verify-full` when possible to prevent man-in-the-middle attacks. ## Read-Only Mode The `read_only` parameter enables database-level read-only enforcement for the connection. **How it works**: After connection, `SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY` is executed automatically. **Effect**: PostgreSQL enforces read-only at the database level - any attempt to INSERT, UPDATE, DELETE, TRUNCATE, or perform other write operations will fail with an error. **When to use**: - **Production agent connections** - Recommended for all AI agent access to prevent accidental data modification - **Analytics/reporting connections** - Ensure reporting tools cannot modify data - **Compliance requirements** - Meet regulatory requirements for read-only access **Example**: ```json { "read_only": true } ``` This provides strong database-level protection against data modification. Unlike role-based permissions, this setting prevents writes regardless of the user's privileges. **Note**: Default is `false` for backward compatibility. We recommend setting `read_only: true` for all new production connections. ## Role-Based Access Control The `role` parameter enables privilege separation - connect with admin credentials but execute queries with restricted permissions. **How it works**: After connection, `SET ROLE ` is executed automatically. **Common pattern** - Use built-in read-only role: ```json { "role": "pg_read_all_data" } ``` This prevents data modification while allowing full read access. ## Description Field The `description` should document your schema to help agents write effective queries. **Example**: ``` Production customer database. Tables: - users: user_id (uuid), email (text), status (text: 'active'/'suspended') - subscriptions: subscription_id (uuid), user_id (uuid), plan_name (text), status (text) - billing_events: event_id (uuid), subscription_id (uuid), event_type (text), amount_cents (int) Common patterns: - Find user by email: WHERE email = '' - Active subscriptions: WHERE status = 'active' ``` ## Example Connection ```json { "display_name": "Production Customer Database", "description": "Production customer database...", "connection_details": { "postgres": { "host": "prod-db.example.com", "port": 5432, "database": "customers", "username": "admin", "password": "password", "ssl_mode": "verify-full", "role": "pg_read_all_data", "read_only": true } } } ``` ## Query Support Firetiger supports standard PostgreSQL query syntax including: - SELECT statements with all standard clauses (WHERE, JOIN, GROUP BY, ORDER BY, LIMIT, etc.) - Common Table Expressions (CTEs) with WITH - SQL comments (both `--` single-line and `/* */` multi-line styles) - All PostgreSQL functions (aggregate, string, date/time, etc.) ## Security Model Firetiger provides multiple layers of security for PostgreSQL connections: 1. **Database-level read-only enforcement** - Use `read_only: true` to prevent writes at the PostgreSQL level 2. **Role-based access control** - Use read-only roles (`pg_read_all_data`) to limit permissions 3. **SSL encryption** - Use `ssl_mode: "verify-full"` for secure connections **Recommended approach**: Enable `read_only: true` for all production agent connections. This provides strong database-level protection regardless of the user's actual permissions. **Defense in depth**: Combine `read_only: true` with a read-only role for maximum protection: - `read_only: true` - Prevents writes even if the role has write permissions - `role: "pg_read_all_data"` - Limits permissions at the database role level ## Best Practices - **Enable read-only mode** - Set `read_only: true` for all production agent connections - **Use read-only roles** - Set `role: "pg_read_all_data"` or custom read-only roles for defense in depth - **Document your schema** - Include table/column information in the description field - **Enable SSL in production** - Use `ssl_mode: "verify-full"` - **Limit data exposure** - Only grant access to necessary tables through PostgreSQL permissions ### MySQL Connections MySQL connections enable agents to query MySQL databases. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Network Configuration Firetiger's query servers must be able to reach your database. Choose the appropriate networking setup based on your database configuration: ### 1. Private Network Database **Scenario**: Database runs in a private VPC/network (AWS, GCP, Azure) **Solution**: Set up a private network connection: - **AWS**: Configure AWS PrivateLink - **GCP**: Configure Private Service Connect - **Azure**: Configure Private Link Contact Firetiger support to coordinate private network setup. ### 2. Public Database with IP Allowlist **Scenario**: Database accepts public connections but restricts access by IP address **Solution**: Add Firetiger's static IP addresses to your database's allowlist - Contact Firetiger support to obtain the static IP addresses for your deployment's query servers - Add these IPs to your database firewall rules or security groups ### 3. Public Database with Standard Authentication **Scenario**: Database accepts public connections with username/password authentication **Solution**: No special networking configuration needed - Ensure your database accepts connections on the standard MySQL port (3306) - Verify firewall allows inbound connections from the internet - Use `ssl_mode: "VERIFY_IDENTITY"` for secure connections ## Connection Parameters A MySQL connection requires the following configuration: ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `host` | string | Database hostname or IP address (e.g., `db.example.com`) | | `port` | int32 | Database port number (typically `3306`) | | `database` | string | Name of the database to connect to | | `username` | string | Username for authentication | | `password` | string | Password for authentication (stored securely as a secret) | ### Optional Parameters | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `ssl_mode` | string | SSL/TLS connection mode (see below) | `PREFERRED` | | `read_only` | bool | Enable database-level read-only enforcement | `false` | ## SSL Modes The `ssl_mode` parameter controls how the connection encrypts data in transit. Choose the appropriate mode based on your security requirements: | Mode | Description | Use When | |------|-------------|----------| | `DISABLED` | No SSL encryption | **Not recommended** - Only for local development or testing | | `PREFERRED` | Use SSL if available, fall back to unencrypted | Default - Provides encryption when the server supports it | | `REQUIRED` | Require SSL but don't verify server certificate | You want encryption but certificate verification isn't critical | | `VERIFY_IDENTITY` | Require SSL, verify certificate, and check hostname matches | **Most secure** - Recommended for production | For production environments, use `VERIFY_IDENTITY` when possible to prevent man-in-the-middle attacks. ## Read-Only Mode The `read_only` parameter enables database-level read-only enforcement for the connection. **How it works**: After connection, `SET SESSION TRANSACTION READ ONLY` is executed automatically. **Effect**: MySQL enforces read-only at the session level - any attempt to INSERT, UPDATE, DELETE, TRUNCATE, or perform other write operations will fail with an error. **When to use**: - **Production agent connections** - Recommended for all AI agent access to prevent accidental data modification - **Analytics/reporting connections** - Ensure reporting tools cannot modify data - **Compliance requirements** - Meet regulatory requirements for read-only access **Example**: ```json { "read_only": true } ``` This provides strong database-level protection against data modification. **Note**: Default is `false` for backward compatibility. We recommend setting `read_only: true` for all new production connections. ## Description Field The `description` should document your schema to help agents write effective queries. **Example**: ``` Production customer database (MySQL 8.0). Tables: - users: user_id (INT, PK), email (VARCHAR), status (ENUM: 'active','suspended') - subscriptions: subscription_id (INT, PK), user_id (INT, FK), plan_name (VARCHAR), status (VARCHAR) - billing_events: event_id (INT, PK), subscription_id (INT, FK), event_type (VARCHAR), amount_cents (INT) Common patterns: - Find user by email: WHERE email = '' - Active subscriptions: WHERE status = 'active' ``` ## Example Connection ```json { "display_name": "Production Customer Database", "description": "Production customer database...", "connection_details": { "mysql": { "host": "prod-db.example.com", "port": 3306, "database": "customers", "username": "admin", "password": "password", "ssl_mode": "VERIFY_IDENTITY", "read_only": true } } } ``` ## Query Support Firetiger supports standard MySQL query syntax including: - SELECT statements with all standard clauses (WHERE, JOIN, GROUP BY, ORDER BY, LIMIT, etc.) - Common Table Expressions (CTEs) with WITH (MySQL 8.0+) - Subqueries and derived tables - SQL comments (both `--` single-line and `/* */` multi-line styles) - All MySQL functions (aggregate, string, date/time, JSON, etc.) - MySQL-specific syntax such as `LIMIT offset, count` and backtick-quoted identifiers ## Security Model Firetiger provides multiple layers of security for MySQL connections: 1. **Database-level read-only enforcement** - Use `read_only: true` to prevent writes at the MySQL session level 2. **SSL encryption** - Use `ssl_mode: "VERIFY_IDENTITY"` for secure connections **Recommended approach**: Enable `read_only: true` for all production agent connections. This provides strong database-level protection regardless of the user's actual permissions. ## Best Practices - **Enable read-only mode** - Set `read_only: true` for all production agent connections - **Document your schema** - Include table/column information in the description field - **Enable SSL in production** - Use `ssl_mode: "VERIFY_IDENTITY"` - **Limit data exposure** - Only grant access to necessary tables through MySQL permissions - **Use a dedicated user** - Create a MySQL user specifically for Firetiger with minimal required privileges ### ClickHouse Connections ClickHouse connections enable agents to query ClickHouse analytical databases. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Network Configuration Firetiger's query servers must be able to reach your ClickHouse instance. Choose the appropriate networking setup based on your deployment: ### 1. ClickHouse Cloud **Scenario**: Managed ClickHouse Cloud instance **Important**: ClickHouse Cloud exposes two ports — `8443` (HTTP protocol) and `9440` (native protocol). Firetiger uses the **native protocol**, so you must connect on port **`9440`** with `secure: true`. Using port `8443` will result in a connection error. **Solution**: Ensure Firetiger's IP addresses are allowed in your ClickHouse Cloud service's IP access list. - Contact Firetiger support to obtain the static IP addresses for your deployment's query servers - Add these IPs in ClickHouse Cloud under **Settings > Security > IP Access List** ### 2. Private Network Database **Scenario**: ClickHouse runs in a private VPC/network (AWS, GCP, Azure) **Solution**: Set up a private network connection: - **AWS**: Configure AWS PrivateLink - **GCP**: Configure Private Service Connect Contact Firetiger support to coordinate private network setup. ### 3. Public Instance with Standard Authentication **Scenario**: ClickHouse accepts public connections with username/password authentication **Solution**: No special networking configuration needed - Ensure your ClickHouse instance accepts connections on the configured port - Verify firewall allows inbound connections - Enable TLS (`secure: true`) for encrypted connections ## Connection Parameters A ClickHouse connection requires the following configuration: ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `host` | string | Database hostname (e.g., `abc.us-east-1.aws.clickhouse.cloud`) | | `database` | string | Name of the database to connect to | | `username` | string | Username for authentication | | `password` | string | Password for authentication (stored securely as a secret) | ### Optional Parameters | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `port` | int32 | Database port number | `9440` | | `secure` | bool | Enable TLS encryption | `true` | ## Ports and Protocols Firetiger connects to ClickHouse using the **native protocol**. The default port depends on whether TLS is enabled: | Configuration | Port | Description | |---------------|------|-------------| | `secure: true` | `9440` | Native protocol with TLS (default) | | `secure: false` | `9000` | Native protocol without TLS | ClickHouse Cloud uses port `9440` by default with TLS enabled. ## TLS (Secure Mode) The `secure` parameter controls whether the connection uses TLS encryption. - **`true` (default)** - TLS enabled. Recommended for all environments, required for ClickHouse Cloud. - **`false`** - TLS disabled. Only use for local development or testing. For production environments, always use `secure: true`. ## Description Field The `description` should document your schema to help agents write effective queries. **Example**: ``` ClickHouse analytics database for event tracking. Tables: - events: event_id (UUID), user_id (String), event_type (String), timestamp (DateTime), properties (String) - page_views: view_id (UUID), user_id (String), url (String), referrer (String), timestamp (DateTime) - sessions: session_id (UUID), user_id (String), start_time (DateTime), duration_seconds (UInt32) Common patterns: - Events in time range: WHERE timestamp >= '2024-01-01' AND timestamp < '2024-02-01' - Aggregate by day: GROUP BY toDate(timestamp) - Top events: SELECT event_type, count() FROM events GROUP BY event_type ORDER BY count() DESC ``` ## Example Connection ```json { "display_name": "Analytics ClickHouse", "description": "ClickHouse analytics database...", "connection_details": { "clickhouse": { "host": "abc.us-east-1.aws.clickhouse.cloud", "port": 9440, "database": "analytics", "username": "readonly_user", "password": "password", "secure": true } } } ``` ## Query Support Firetiger supports standard ClickHouse SQL syntax including: - SELECT statements with all standard clauses (WHERE, JOIN, GROUP BY, ORDER BY, LIMIT, etc.) - Common Table Expressions (CTEs) with WITH - ClickHouse-specific functions (toDate, toDateTime, formatDateTime, etc.) - Aggregate functions (count, sum, avg, uniq, quantile, etc.) - Array and map functions - SQL comments (both `--` single-line and `/* */` multi-line styles) Query results are streamed with a timeout of 5 minutes. ## Security Model Firetiger provides multiple layers of security for ClickHouse connections: 1. **Read-only users** - Create a dedicated read-only ClickHouse user for Firetiger 2. **TLS encryption** - Use `secure: true` for encrypted connections 3. **Network restrictions** - Use IP allowlists or private networking to restrict access **Recommended approach**: Create a dedicated read-only user in ClickHouse with access limited to the necessary databases and tables. **Example** - Create a read-only user in ClickHouse: ```sql CREATE USER firetiger_reader IDENTIFIED BY 'secure_password'; GRANT SELECT ON analytics.* TO firetiger_reader; ``` ## Best Practices - **Use a read-only user** - Create a dedicated ClickHouse user with only SELECT permissions - **Enable TLS** - Set `secure: true` for all production connections - **Document your schema** - Include table/column information and common query patterns in the description field - **Limit database access** - Only grant access to necessary databases and tables - **Use ClickHouse Cloud defaults** - Port `9440` with `secure: true` for ClickHouse Cloud instances ## Infrastructure Ingest data from and connect to cloud infrastructure providers. ### AWS Connections AWS connections enable Firetiger to access your AWS resources using IAM role assumption (STS AssumeRole). This provides secure, temporary credentials without sharing long-term access keys. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Setup Overview Setting up an AWS connection involves two steps: 1. **Deploy CloudFormation Stack** - Creates an IAM role in your AWS account that Firetiger can assume 2. **Create Connection** - Enter the Role ARN and External ID from the CloudFormation outputs ## Step 1: Deploy CloudFormation Stack ### Option A: AWS Console (One-Click) 1. Navigate to **Settings > Connections** in the Firetiger UI 2. Click **New Connection** and select **AWS** 3. Select your AWS region 4. Click **Launch Stack in AWS Console** 5. Review the stack parameters and click **Create stack** 6. Wait for the stack to complete (typically 2-3 minutes) ### Option B: AWS CLI ```bash aws cloudformation create-stack \ --stack-name firetiger-cloudwatch-logs \ --template-url https://firetiger-public.s3.us-west-2.amazonaws.com/ingest/aws/cloudwatch/logs/ingest-and-iam-onboarding.yaml \ --parameters \ "ParameterKey=FiretigerEndpoint,ParameterValue={{ site.ingest_url }}" \ "ParameterKey=FiretigerUsername,ParameterValue={your-username}" \ "ParameterKey=FiretigerPassword,ParameterValue={your-password}" \ --capabilities CAPABILITY_NAMED_IAM \ --region us-east-1 ``` Replace `{your-username}` and `{your-password}` with your Firetiger credentials. ## Step 2: Get CloudFormation Outputs After the stack completes, retrieve the outputs: **AWS Console:** 1. Go to CloudFormation > Stacks > firetiger-cloudwatch-logs 2. Click the **Outputs** tab 3. Copy the values for `FiretigerRoleArn` and `FiretigerExternalId` **AWS CLI:** ```bash aws cloudformation describe-stacks \ --stack-name firetiger-cloudwatch-logs \ --query 'Stacks[0].Outputs' \ --output table ``` ## Step 3: Create the Connection 1. In the Firetiger UI, enter the **Role ARN** from the CloudFormation outputs 2. Enter the **External ID** from the CloudFormation outputs 3. Select the **AWS Region** where your resources are located 4. Click **Create Connection** ## Connection Fields | Field | Required | Description | |-------|----------|-------------| | `display_name` | Yes | Human-readable name (e.g., "Production AWS") | | `description` | Yes | Description of what this connection accesses | | `role_arn` | Yes | IAM Role ARN to assume (e.g., `arn:aws:iam::123456789012:role/firetiger-access`) | | `external_id` | No | External ID for additional security (recommended) | | `region` | Yes | AWS region (default: `us-east-1`) | | `session_duration_seconds` | No | How long credentials are valid (900-43200, default: 3600) | ## What the CloudFormation Stack Creates The stack deploys: | Resource | Purpose | |----------|---------| | Lambda Function | Processes CloudWatch logs and forwards to Firetiger | | IAM Role (Lambda) | Allows Lambda to read CloudWatch logs | | IAM Role (Firetiger) | Cross-account role that Firetiger assumes | | Subscription Filters | Automatically subscribes to matching log groups | | CloudWatch Log Group | Stores Lambda function logs | ## IAM Role Permissions The IAM role created for Firetiger has read-only access: ```json { "Effect": "Allow", "Action": [ "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:GetLogEvents", "logs:FilterLogEvents" ], "Resource": "*" } ``` ## Security ### External ID The External ID prevents the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.txt). When configured: - Only requests with the matching External ID can assume the role - The CloudFormation stack generates a unique External ID automatically - Always use the External ID provided in the stack outputs ### Credential Rotation Firetiger automatically: - Requests new STS credentials before expiration - Caches credentials with a 5-minute expiry buffer - Uses unique session names for CloudTrail auditing ## Verification After creating the connection, Firetiger automatically verifies it by: 1. Calling STS AssumeRole with your Role ARN and External ID 2. Making a test API call (sts:GetCallerIdentity) 3. Confirming the assumed role identity If verification fails, check: - The Role ARN is correct and the role exists - The External ID matches exactly - The role's trust policy allows Firetiger's AWS account ## Troubleshooting ### "Access Denied" when assuming role - Verify the Role ARN is correct - Check the External ID matches the CloudFormation output exactly - Ensure the role's trust policy includes Firetiger's AWS account ### "Role does not exist" - Confirm the CloudFormation stack completed successfully - Check you're using the correct AWS region ### Credentials expire too quickly - Increase `session_duration_seconds` (max 43200 = 12 hours) - Note: The IAM role's max session duration must also allow this ## Best Practices - **Use descriptive names** - Include environment and purpose (e.g., "Production CloudWatch Logs") - **Document access scope** - Describe which log groups or resources are accessible - **Use External ID** - Always configure for cross-account security - **Limit permissions** - The default role has read-only access; don't add write permissions unless needed ### GCP Connections GCP connections enable Firetiger to access Google Cloud Platform resources using service account authentication. This provides scoped access to GCP APIs through a service account key. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Setup Overview Setting up a GCP connection involves two steps: 1. **Create a Service Account** - Create a GCP service account with appropriate permissions 2. **Create Connection** - Upload the service account key JSON to Firetiger ## Step 1: Create a Service Account ### Google Cloud Console 1. Go to [IAM & Admin > Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) 2. Click **Create Service Account** 3. Enter a name (e.g., `firetiger-reader`) and description 4. Grant the **Viewer** role (or more restrictive custom role) 5. Click **Done** 6. Click the service account, go to **Keys > Add Key > Create New Key** 7. Select **JSON** and click **Create** 8. Save the downloaded key file securely ### gcloud CLI ```bash # Create the service account gcloud iam service-accounts create firetiger-reader \ --display-name="Firetiger Reader" # Grant Viewer role on the project gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:firetiger-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/viewer" # Create and download a key gcloud iam service-accounts keys create key.json \ --iam-account="firetiger-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com" ``` ## Step 2: Create the Connection 1. In the Firetiger UI, click **New Connection** and select **GCP** 2. Enter your **Project ID** 3. Select the **Region** where your resources are located 4. Paste the contents of your service account key JSON file 5. Click **Create Connection** ## Connection Fields | Field | Required | Description | |-------|----------|-------------| | `display_name` | Yes | Human-readable name (e.g., "Production GCP") | | `description` | Yes | Description of what this connection accesses | | `project_id` | Yes | Default GCP project ID for API calls | | `region` | Yes | Default GCP region (e.g., `us-central1`) | | `service_account_key` | Yes | Service account key in JSON format (write-only) | ### Supported Regions | Region | Location | |--------|----------| | `us-central1` | Iowa | | `us-east1` | South Carolina | | `us-east4` | Northern Virginia | | `us-west1` | Oregon | | `us-west2` | Los Angeles | | `europe-west1` | Belgium | | `europe-west2` | London | | `europe-west3` | Frankfurt | | `asia-east1` | Taiwan | | `asia-southeast1` | Singapore | | `asia-northeast1` | Tokyo | | `australia-southeast1` | Sydney | ## Service Account Key The service account key is a JSON file that looks like: ```json { "type": "service_account", "project_id": "your-project-id", "private_key_id": "key-id", "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", "client_email": "firetiger-reader@your-project-id.iam.gserviceaccount.com", "client_id": "123456789", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/...", "universe_domain": "googleapis.com" } ``` The `type` field must be `"service_account"`. The private key is stored securely and is never returned after creation. ## Verification After creating the connection, Firetiger automatically verifies it by: 1. Creating credentials from the service account key 2. Calling the Cloud Resource Manager API to get project info 3. Confirming the service account has access to the specified project If verification fails, check: - The service account key JSON is valid and complete - The service account has not been deleted or disabled - The project ID matches the service account's project (or the account has cross-project access) - The service account has sufficient IAM permissions ## Security ### Key Management - Service account keys are stored encrypted and never returned after creation - Rotate keys periodically using `gcloud iam service-accounts keys create` - Delete old keys after rotation: `gcloud iam service-accounts keys delete KEY_ID` ### Least Privilege Grant only the minimum IAM roles needed: - **Viewer** (`roles/viewer`) - Read-only access to all resources (broad) - **Custom roles** - Create a custom role with only the specific permissions needed ### Key Rotation To rotate a service account key: 1. Create a new key for the service account 2. Update the Firetiger connection with the new key 3. Verify the connection works 4. Delete the old key from GCP ## Troubleshooting ### "Permission denied" errors - Verify the service account has the correct IAM roles - Check that the project ID in the connection matches the target project - Ensure the service account hasn't been disabled ### "Invalid key" errors - Confirm the JSON is complete and properly formatted - Check that `type` is `"service_account"` - Verify the key hasn't been deleted in GCP ### Connection verification fails - Ensure the service account has at least `resourcemanager.projects.get` permission - The **Viewer** role includes this permission ## Best Practices - **Use descriptive names** - Include environment and purpose (e.g., "Production BigQuery Access") - **Document access scope** - Describe which GCP resources and APIs are accessible - **Follow least privilege** - Grant only the IAM roles needed for the specific use case - **Rotate keys regularly** - Create new keys and delete old ones periodically - **Use dedicated service accounts** - Create a separate service account for Firetiger rather than reusing existing ones ### AWS CloudWatch Logs # Send AWS Cloudwatch Logs to Firetiger The easiest way to ingest Cloudwatch Logs is to deploy one of our Cloudwatch Log Ingest Integrations ### Deploy via Terraform The terraform module can be found here in git, along with instructions on how to configure and deploy: [https://github.com/firetiger-inc/public/tree/main/aws/](https://github.com/firetiger-inc/public/tree/main/aws/) ### Deploy via Cloudformation Documentation: [https://github.com/firetiger-inc/public/tree/main/aws/](https://github.com/firetiger-inc/public/tree/main/aws/) ### AWS ECS Events # Send AWS ECS Events to Firetiger AWS ECS Events provide rich information about your ECS Task health and lifecycle, including: Container Failures, OOMKilled Events, and other signal helpful in triaging ECS application issues. The easiest way to ingest ECS Events is to deploy our ECS Event Ingest Integration ### Deploy via Terraform The terraform module can be found here in git, along with instructions on how to configure and deploy: [https://github.com/firetiger-inc/public](https://github.com/firetiger-inc/public) ### Deploy via Cloudformation [https://github.com/firetiger-inc/public](https://github.com/firetiger-inc/public) ### CloudFront Kinesis Integration # CloudFront to Firetiger Integration via Kinesis Data Firehose This guide explains how to configure AWS CloudFront real-time logs to stream to Firetiger using Kinesis Data Streams and Kinesis Data Firehose. ## Prerequisites - AWS Account with CloudFront distributions - Firetiger deployment with ingest endpoint accessible from AWS - IAM permissions to create Kinesis resources and modify CloudFront configurations - Firetiger API credentials for authentication ## Architecture Overview ``` CloudFront → Kinesis Data Stream → Kinesis Data Firehose → Firetiger Ingest API ``` ## Step 1: Create Kinesis Data Stream First, create a Kinesis Data Stream to receive CloudFront real-time logs: ```bash aws kinesis create-stream \ --stream-name cloudfront-logs-stream \ --shard-count 1 \ --region us-east-1 ``` Wait for the stream to become active: ```bash aws kinesis describe-stream \ --stream-name cloudfront-logs-stream \ --region us-east-1 ``` ## Step 2: Configure CloudFront Real-time Logs ### Via AWS Console 1. Navigate to CloudFront in AWS Console 2. Select your distribution 3. Go to the "Telemetry" tab 4. Under "Real-time logs", click "Create configuration" 5. Configure the following: - **Name**: `firetiger-realtime-logs` - **Sampling rate**: 100 (adjust based on volume) - **Fields**: Select all fields or customize based on your needs - **Endpoint**: Select "Kinesis Data Streams" - **Stream**: Select `cloudfront-logs-stream` - **IAM Role**: Create new role with Kinesis write permissions ### Via AWS CLI ```bash aws cloudfront create-realtime-log-config \ --name firetiger-realtime-logs \ --stream-type Kinesis \ --kinesis-stream-config StreamArn=arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/cloudfront-logs-stream,RoleArn=arn:aws:iam::ACCOUNT_ID:role/CloudFrontRealtimeLogRole \ --fields timestamp,c-ip,s-ip,time-to-first-byte,sc-status,sc-bytes,cs-method,cs-protocol,cs-host,cs-uri-stem,cs-bytes,x-edge-location,x-edge-request-id,x-host-header,time-taken,cs-protocol-version,c-ip-version,cs-user-agent,cs-referer,cs-cookie,cs-uri-query,x-edge-response-result-type,x-forwarded-for,ssl-protocol,ssl-cipher,x-edge-result-type,c-country \ --sampling-rate 100 ``` ## Step 3: Create IAM Role for Kinesis Data Firehose Create an IAM role that allows Kinesis Data Firehose to read from the stream: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "firehose.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } ``` Attach the following policy: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kinesis:DescribeStream", "kinesis:GetShardIterator", "kinesis:GetRecords", "kinesis:ListShards" ], "Resource": "arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/cloudfront-logs-stream" }, { "Effect": "Allow", "Action": [ "logs:PutLogEvents", "logs:CreateLogGroup", "logs:CreateLogStream" ], "Resource": "*" } ] } ``` ## Step 4: Create Kinesis Data Firehose Delivery Stream To configure the Delivery Stream, you'll need your organization's Firetiger Ingest username and password credentials. These can be found in the Firetiger UI on the /settings page: `{{ site.ui_url }}/settings`. Substitute those values for `$FIRETIGER_USERNAME` and `$FIRETIGER_PASSWORD` in the following commands: ### Via AWS CLI ```bash export ACCESS_KEY=$(echo -n "$FIRETIGER_USERNAME:$FIRETIGER_PASSSWORD" | base64) aws firehose create-delivery-stream \ --delivery-stream-name cloudfront-to-firetiger \ --delivery-stream-type KinesisStreamAsSource \ --kinesis-stream-source-configuration '{ "KinesisStreamARN": "arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/cloudfront-logs-stream", "RoleARN": "arn:aws:iam::ACCOUNT_ID:role/firehose-role" }' \ --http-endpoint-destination-configuration '{ "EndpointConfiguration": { "Url": "{{ site.ingest_url }}/aws/cloudfront/kinesis?fields=timestamp,c-ip,s-ip,time-to-first-byte,sc-status,sc-bytes,cs-method,cs-protocol,cs-host,cs-uri-stem,cs-bytes,x-edge-location,x-edge-request-id,x-host-header,time-taken,cs-protocol-version,c-ip-version,cs-user-agent,cs-referer,cs-cookie,cs-uri-query,x-edge-response-result-type,x-forwarded-for,ssl-protocol,ssl-cipher,x-edge-result-type,c-country", "Name": "Firetiger", "AccessKey": "$ACCESS_KEY" }, "BufferingHints": { "IntervalInSeconds": 60, "SizeInMBs": 1 }, "CompressionFormat": "GZIP", "RequestConfiguration": { "ContentEncoding": "GZIP" }, "RetryConfiguration": { "DurationInSeconds": 3600 }, "S3Configuration": { "BucketARN": "arn:aws:s3:::your-backup-bucket", "Prefix": "failed-records/", "ErrorOutputPrefix": "error-records/", "CompressionFormat": "GZIP", "RoleARN": "arn:aws:iam::ACCOUNT_ID:role/firehose-role" } }' ``` ### Configuration Parameters - **Url**: Your Firetiger ingest endpoint - `{{ site.ingest_url }}/aws/cloudfront/kinesis` - **AccessKey**: Your basic-auth Firetiger ingest credentials, as shown above - **BufferingHints**: - `IntervalInSeconds`: How often to send data (60-900 seconds) - `SizeInMBs`: Buffer size before sending (1-128 MB) - **CompressionFormat**: Use GZIP to reduce bandwidth - **S3Configuration**: Backup location for failed records ## Step 5: Attach CloudFront Distribution to Real-time Log Configuration ```bash aws cloudfront update-distribution \ --id YOUR_DISTRIBUTION_ID \ --realtime-log-config-arn arn:aws:cloudfront::ACCOUNT_ID:realtime-log-config/firetiger-realtime-logs ``` ## Step 6: Verify Data Flow After configuration, verify that logs are flowing: 1. Generate some traffic to your CloudFront distribution 2. Monitor Kinesis Data Stream metrics in CloudWatch 3. Check Kinesis Data Firehose metrics for successful deliveries 4. Query your data in Firetiger to confirm ingestion ## Troubleshooting ### Common Issues 1. **Authentication Failures** - Verify your API key is correct - Ensure the endpoint URL includes the correct protocol (https) 2. **No Data Flowing** - Check CloudWatch Logs for Kinesis Data Firehose error messages - Verify IAM roles have correct permissions - Ensure CloudFront distribution is attached to the real-time log configuration 3. **High Error Rate** - Check the S3 backup bucket for failed records - Review error messages in CloudWatch Logs - Verify endpoint is accessible from AWS ## Advanced Configuration ### Custom Field Selection CloudFront allows you to customize which fields to include in real-time logs. This is useful for reducing data volume and costs. You can configure this when creating or updating your CloudFront real-time log configuration: ```bash aws cloudfront update-realtime-log-config \ --name firetiger-realtime-logs \ --fields timestamp,c-ip,sc-status,cs-method,cs-uri-stem,x-edge-location ``` **Important:** When you customize CloudFront fields, you must also update your Kinesis Data Firehose endpoint URL to specify which fields you're sending. This ensures Firetiger parses the log records correctly. #### Configuring Firetiger for Custom Fields When configuring custom CloudFront fields, add a `?fields=` query parameter to your Firehose endpoint URL that lists the fields in the same order as your CloudFront configuration: ```bash export ACCESS_KEY=$(echo -n "$FIRETIGER_USERNAME:$FIRETIGER_PASSWORD" | base64) aws firehose create-delivery-stream \ --delivery-stream-name cloudfront-to-firetiger \ --delivery-stream-type KinesisStreamAsSource \ --kinesis-stream-source-configuration '{ "KinesisStreamARN": "arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/cloudfront-logs-stream", "RoleARN": "arn:aws:iam::ACCOUNT_ID:role/firehose-role" }' \ --http-endpoint-destination-configuration '{ "EndpointConfiguration": { "Url": "{{ site.ingest_url }}/aws/cloudfront/kinesis?fields=timestamp,c-ip,sc-status,cs-method,cs-uri-stem,x-edge-location", "Name": "Firetiger", "AccessKey": "$ACCESS_KEY" }, ... }' ``` #### Field Mapping Examples **Default (All Fields):** If you don't specify a `?fields=` parameter, Firetiger expects all 45 standard CloudFront fields in canonical order. This is the recommended configuration for most use cases. ``` {{ site.ingest_url }}/aws/cloudfront/kinesis ``` **Minimal Fields:** For cost-sensitive deployments, you can send only essential fields: ``` {{ site.ingest_url }}/aws/cloudfront/kinesis?fields=timestamp,c-ip,sc-status,cs-method,cs-uri-stem ``` **Custom Fields:** Select specific fields based on your analytics needs: ``` {{ site.ingest_url }}/aws/cloudfront/kinesis?fields=timestamp,c-ip,cs-method,cs-host,cs-uri-stem,sc-status,sc-bytes,time-taken,cs-user-agent,x-edge-location,x-edge-response-result-type ``` **Important Notes:** 1. **Field names** must match CloudFront field names exactly (e.g., `timestamp`, `c-ip`, `sc-status`) 2. **Field order** must match your CloudFront real-time log configuration exactly - CloudFront always sends fields in canonical order 3. **Changing fields**: If you add or remove fields in your CloudFront configuration, you **must** update your Kinesis Data Firehose URL to match the new field list. AWS automatically reorders fields in canonical order when you modify the configuration. 4. Field names are comma-separated with no spaces 5. The query parameter can handle all 45 standard fields 6. If you omit fields from your CloudFront configuration, those attributes will not be populated in Firetiger **Example of field ordering:** - Initial CloudFront config: `time-to-first-byte, sc-status, c-country` (3 fields) - Firehose URL: `?fields=time-to-first-byte,sc-status,c-country` - Later you add `sc-bytes` and `time-taken` to CloudFront - CloudFront automatically reorders to: `time-to-first-byte, sc-status, sc-bytes, time-taken, c-country` (canonical order) - You **must** update Firehose URL to: `?fields=time-to-first-byte,sc-status,sc-bytes,time-taken,c-country` - The `c-country` field moves from position 3 to position 5 in the log records ### Multi-Region Setup For global distributions, consider: 1. Creating Kinesis streams in multiple regions 2. Using cross-region replication 3. Configuring regional Firehose delivery streams ## CloudFront Log Format Details ### Real-time Log Fields CloudFront real-time logs are delivered as **tab-delimited** records with 40-69 fields (depending on configuration). Each record in the Kinesis Data Firehose payload is base64-encoded. **Note:** AWS has expanded the CloudFront real-time log format over time. Firetiger supports: - Fields 1-45: Fully parsed with structured field names - Fields 46-69+: Gracefully ignored (CMCD media streaming fields and future extensions) The fields are: #### Core Fields (1-41) 1. **timestamp** - Unix timestamp with milliseconds (e.g., 1733270958.123) 2. **c-ip** - Client IP address 3. **s-ip** - CloudFront server IP address 4. **time-to-first-byte** - Time to first byte in seconds 5. **sc-status** - HTTP status code 6. **sc-bytes** - Response size in bytes 7. **cs-method** - HTTP method (GET, POST, etc.) 8. **cs-protocol** - Protocol (http/https) 9. **cs-host** - Host header value 10. **cs-uri-stem** - URI path 11. **cs-bytes** - Request size in bytes 12. **x-edge-location** - CloudFront edge location code 13. **x-edge-request-id** - Unique request identifier 14. **x-host-header** - Host header sent to origin 15. **time-taken** - Total time taken in seconds 16. **cs-protocol-version** - HTTP protocol version 17. **c-ip-version** - IP version (IPv4/IPv6) 18. **cs-user-agent** - User agent string 19. **cs-referer** - Referer header 20. **cs-cookie** - Cookie header 21. **cs-uri-query** - Query string 22. **x-edge-response-result-type** - Cache result (Hit, Miss, Error) 23. **x-forwarded-for** - X-Forwarded-For header 24. **ssl-protocol** - SSL/TLS protocol version 25. **ssl-cipher** - SSL/TLS cipher suite 26. **x-edge-result-type** - How request was classified 27. **fle-encrypted-fields** - Field-level encryption 28. **fle-status** - Field-level encryption status 29. **sc-content-type** - Response content type 30. **sc-content-len** - Response content length 31. **sc-range-start** - Range request start 32. **sc-range-end** - Range request end 33. **c-port** - Client port 34. **x-edge-detailed-result-type** - Detailed result type 35. **c-country** - Client country code 36. **cs-accept-encoding** - Accept-Encoding header 37. **cs-accept** - Accept header 38. **cache-behavior-path-pattern** - Cache behavior pattern 39. **cs-headers** - Custom headers 40. **cs-header-names** - Custom header names 41. **cs-headers-count** - Count of custom headers #### Extended Fields (42-45, added October 2022) 42. **primary-distribution-id** - Primary distribution identifier 43. **primary-distribution-dns-name** - Primary distribution DNS name 44. **origin-fbl** - Origin first-byte latency (time from edge to origin's first byte, in seconds) 45. **origin-lbl** - Origin last-byte latency (time from edge to origin's last byte, in seconds) #### CMCD and Extended Fields (46-69+, added April 2024) Fields 46 and beyond are gracefully ignored but accepted in log records. The known CMCD field names are: 46. **asn** - Autonomous system number 47. **c-asn** - Client autonomous system number 48. **cmcd-buffer-length** - CMCD buffer length (milliseconds) 49. **cmcd-buffer-starvation** - CMCD buffer starvation indicator 50. **cmcd-content-id** - CMCD content identifier 51. **cmcd-deadline** - CMCD playback deadline 52. **cmcd-encoded-bitrate** - CMCD encoded bitrate (kbps) 53. **cmcd-measured-throughput** - CMCD measured throughput (kbps) 54. **cmcd-next-object-request** - CMCD next object request 55. **cmcd-next-range-request** - CMCD next range request 56. **cmcd-object-duration** - CMCD object duration (milliseconds) 57. **cmcd-object-type** - CMCD object type (m=manifest, a=audio, v=video, etc.) 58. **cmcd-playback-rate** - CMCD playback rate 59. **cmcd-requested-maximum-throughput** - CMCD requested max throughput 60. **cmcd-startup** - CMCD startup indicator 61. **cmcd-stream-type** - CMCD stream type (v=VOD, l=live) 62. **cmcd-streaming-format** - CMCD streaming format (d=DASH, h=HLS, etc.) 63. **cmcd-top-bitrate** - CMCD top bitrate (kbps) 64. **cmcd-version** - CMCD version 65. **r-host** - Request host 66. **sc-range-count** - Range request count 67. **sc-response-body-time** - Response body time 68. **sr-reason** - Server reason code 69. **x-sc-response-body-time** - Extended response body time These fields are only present if configured in your CloudFront real-time log configuration. CMCD fields are primarily used for media streaming analytics and are sent by compatible media players. Firetiger accepts but does not parse these fields. For complete documentation, see the [AWS CloudFront Real-time Logs documentation](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.txt). #### Field Value Conventions - Fields with no value are represented as `-` (hyphen) - Numeric fields use standard decimal notation - Timestamps use Unix epoch format with decimal seconds (e.g., 1733270958.123) ### Kinesis Data Firehose Request Format The HTTP request from Kinesis Data Firehose follows this structure: ```json { "requestId": "ed4acda5-034f-9f42-bba1-f29aea6d7d8f", "timestamp": 1733270958000, "records": [ { "data": "MTczMzI3MDk1OC4xMjMJMTkyLjE2OC4xLjEJ..." } ] } ``` - `requestId`: Unique identifier for the Firehose request (matches X-Amz-Firehose-Request-Id header) - `timestamp`: Unix timestamp in milliseconds when the request was created - `records`: Array of base64-encoded CloudFront log records ### Expected Response Format Firetiger must respond with the following format: Success (200 OK): ```json { "requestId": "ed4acda5-034f-9f42-bba1-f29aea6d7d8f", "timestamp": 1733270958123 } ``` Error (4xx/5xx): ```json { "requestId": "ed4acda5-034f-9f42-bba1-f29aea6d7d8f", "timestamp": 1733270958123, "errorMessage": "Error description" } ``` ### Cloudflare Workers Integration Export traces and logs from your [Cloudflare Workers](https://developers.cloudflare.com/workers/) directly to Firetiger using built-in OpenTelemetry support. No additional packages or bindings are required. This guide covers **application-level telemetry** from your Worker code (traces, `console.log()` output, and system logs). For **HTTP request logs** from Cloudflare's edge network, see the [Cloudflare Logpush Integration](cloudflare-logpush.txt). ## Prerequisites - An active Firetiger deployment - A Cloudflare account with at least one deployed Worker - Access to the [Cloudflare dashboard](https://dash.cloudflare.com) or `wrangler` CLI ## Step 1: Get your Firetiger ingest credentials 1. Log in to your Firetiger account 2. Navigate to the **Integrations** page 3. Copy your **Ingest Basic Auth Credentials** (endpoint, username, and password) Generate the Base64-encoded credentials: ```bash echo -n "username:password" | base64 ``` Replace `username` and `password` with the values from your Integrations page. ## Step 2: Create OTLP destinations in Cloudflare In the Cloudflare dashboard, go to **Compute & AI > Workers Observability > Destinations**. ### Traces destination Click **Add destination** and configure: | Field | Value | | :----------------- | :--------------------------------------------------------------------------- | | Destination name | `firetiger-traces` | | Destination type | Traces | | OTLP endpoint | `{{ site.ingest_url }}/v1/traces` | | Custom header name | `Authorization` | | Custom header value| `Basic ` | ### Logs destination Click **Add destination** again and configure: | Field | Value | | :----------------- | :--------------------------------------------------------------------------- | | Destination name | `firetiger-logs` | | Destination type | Logs | | OTLP endpoint | `{{ site.ingest_url }}/v1/logs` | | Custom header name | `Authorization` | | Custom header value| `Basic ` | Replace `` with the output from the base64 command above. ## Step 3: Enable observability on your Worker You can enable observability via the dashboard or `wrangler.toml`. ### Option A: Dashboard 1. Go to **Compute & AI > Workers & Pages** 2. Select your Worker 3. Go to **Settings > Observability** 4. Enable traces and logs, and select the `firetiger-traces` and `firetiger-logs` destinations ### Option B: wrangler.toml Add the following to your Worker's `wrangler.toml`: ```toml [observability.traces] enabled = true head_sampling_rate = 1.0 destinations = ["firetiger-traces"] [observability.logs] enabled = true head_sampling_rate = 1.0 destinations = ["firetiger-logs"] ``` Adjust `head_sampling_rate` as needed (1.0 = 100% of requests, 0.01 = 1%). ## Step 4: Deploy and verify 1. Deploy your Worker with `wrangler deploy` 2. Send a few requests to your Worker 3. Log in to Firetiger and check your traces and logs views Traces will include the full request lifecycle through your Worker, and logs will include all `console.log()` output and system-generated logs. ## What data is exported | Signal | Included | | :------ | :----------------------------------------------------------------------- | | Traces | Request lifecycle spans, sub-requests, bindings (KV, D1, R2, etc.) | | Logs | `console.log()` / `console.error()` output, system-generated logs | | Metrics | Not yet supported by Cloudflare Workers observability | ## Sampling Cloudflare applies head-based sampling at the edge. The `head_sampling_rate` controls what percentage of requests produce telemetry: - `1.0` - Export telemetry for every request (recommended for low-traffic Workers) - `0.1` - Export for 10% of requests - `0.01` - Export for 1% of requests (recommended for high-traffic Workers) When a request is sampled, all traces and logs for that request are exported together. ## Troubleshooting **No data appearing in Firetiger?** - Verify the OTLP endpoints are correct (check for typos in the deployment name) - Ensure the `Authorization` header value includes the `Basic ` prefix - Confirm the destinations are selected on the Worker's observability settings - Check that `head_sampling_rate` is not set to `0` - Try setting `head_sampling_rate = 1.0` temporarily to rule out sampling **Authentication errors?** - Re-generate your Base64 credentials and update the destination header value - Ensure there are no extra spaces or newlines in the credentials ## Related documentation - [Cloudflare Workers Observability: Exporting OpenTelemetry Data](https://developers.cloudflare.com/workers/observability/exporting-opentelemetry-data/) - [Cloudflare Logpush Integration](cloudflare-logpush.txt) - For HTTP request logs from Cloudflare's edge - [OpenTelemetry Integration](../../guides/opentelemetry.txt) - For sending OTLP data from other sources ### Cloudflare Logpush Integration Firetiger supports ingesting Cloudflare Logpush data via direct HTTP endpoints. ## Setup ### Configure Cloudflare Logpush You can find your Firetiger ingest credentials (endpoint, username, and password) on the **Integrations** page in the Firetiger console. To generate the Base64-encoded credentials for the URL: ```bash echo -n "username:password" | base64 | sed 's/=/%3D/g' ``` Replace `username` and `password` with the values from your Integrations page. This command also URL-encodes any `=` padding characters in the Base64 output. 1. Login to the [Cloudflare Dashboard](https://dash.cloudflare.com) 2. Navigate to your domain's **Analytics & Logs** > **Logpush** 3. Click **Create a Logpush Job** 4. Select **HTTP Destination** 5. Configure the HTTP endpoint URL with authentication: ``` {{ site.ingest_url }}/cloudflare/logpush/http_requests?header_Authorization=Basic%20 ``` Replace `` with the output from the base64 command above. Note: The `header_Authorization` URL parameter sets the HTTP Authorization header. The space after "Basic" must be URL-encoded as `%20`. 6. Select the **HTTP Requests** dataset 7. Configure job settings - **Job Name**: Choose a descriptive name (e.g., `firetiger-http-requests`) - **Fields**: Select the fields you want to push (recommend selecting all fields) - **Advanced > Log Delivery Method**: Choose `Edge` for lowest latency 8. Save and enable the job ## Related Documentation - [Cloudflare Logpush Documentation](https://developers.cloudflare.com/logs/get-started/) - [Cloudflare HTTP Destination Setup](https://developers.cloudflare.com/logs/logpush/logpush-job/enable-destinations/http/) - [Cloudflare HTTP Requests Schema](https://developers.cloudflare.com/logs/reference/log-fields/zone/http_requests/) ## Developer Tools Integrate Firetiger with developer and incident management tools. ### GitHub Connections > **Note:** Codebase Search currently does not handle large numbers of repositories well. Improving this integration is on our roadmap. GitHub connections enable agents to access your repositories for codebase context during investigations, and ingest GitHub events (pushes, pull requests, workflow runs, etc.). **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Installation 1. Navigate to **Settings > Connections** in the Firetiger UI 2. Click **New Connection** 3. Select **GitHub** as the connection type 4. Click **Connect GitHub** 5. You will be redirected to GitHub to authorize the Firetiger GitHub App 6. Select the GitHub organization or user account where you want to install the app 7. Choose which repositories to grant access to (all repositories or select specific ones) 8. Confirm the installation The connection will be created automatically with your GitHub account details. GitHub will automatically send webhook events to Firetiger for the selected repositories. ## What Gets Created When you install the GitHub app, Firetiger automatically creates a connection with: | Field | Value | |-------|-------| | `connection_id` | `github-{installation_id}` | | `display_name` | Your GitHub organization or user name | | `description` | `GitHub: {account_name}` | ## Permissions The Firetiger GitHub App requests the following permissions: | Permission | Access | Purpose | |------------|--------|---------| | Repository contents | Read | Access code for context during investigations | | Metadata | Read | Basic repository information | | Pull requests | Read | PR details and status | | Actions | Read | Workflow and job information | ## Updating Repository Access To add or remove repositories from your GitHub connection: 1. Navigate to the [Firetiger GitHub App page](https://github.com/apps/firetiger-agent) 2. Click **Configure** 3. Select your GitHub organization or user account 4. Under **Repository access**, choose: - **All repositories** - Grant access to all current and future repositories - **Only select repositories** - Choose specific repositories to grant access to 5. Click **Save** Changes take effect immediately. Firetiger will automatically update the available repositories for codebase search. ## Re-authorization To reconnect or fix authentication issues: 1. Navigate to **Settings > Connections** in the Firetiger UI 2. Find your GitHub connection 3. Click **Reconnect** or delete and recreate the connection ## Capabilities GitHub connections enable: - **Codebase context** - Agents can search and read repository code during investigations - **Event ingestion** - Automatic ingestion of GitHub events (pushes, PRs, workflow runs) - **Repository insights** - Activity tracking and change history ## Description Field The `description` field helps agents understand which repositories and use cases this connection covers. **Example**: ``` Production infrastructure repositories. Key repositories: - firetiger-inc/core - Main application code - firetiger-inc/infra - Terraform and deployment configs - firetiger-inc/docs - Documentation Use for investigating deployment issues, code changes, and CI/CD failures. ``` ## Best Practices - **Limit repository access** - Only grant access to repositories that agents need for investigations - **Use descriptive names** - Helps agents select the right connection when multiple GitHub accounts are connected - **Document repository purposes** - Include which repositories are relevant for different investigation types ## GitHub App Page The Firetiger GitHub App is available at: [https://github.com/apps/firetiger-agent](https://github.com/apps/firetiger-agent) ## Related Documentation - [GitHub Webhook Ingestion](./github-webhook.txt) - Details on GitHub event ingestion - [GitHub Apps Documentation](https://docs.github.com/en/apps) ### GitHub Webhooks When you install the [Firetiger GitHub App](./github.txt), Firetiger automatically ingests GitHub webhook events for your connected repositories. ## Supported Events The following event types are captured: - **Push events** - Code pushes to branches - **Pull request events** - PR opened, closed, merged, etc. - **Workflow run events** - GitHub Actions workflow executions - **Workflow job events** - Individual job status within workflows - **Check run events** - CI/CD check results - **Check suite events** - Groups of check runs - **Installation events** - App installation changes ## Table All GitHub events are stored in the `github_events` table. ### Incident.io ## Setup Instructions ### 1. Create API Key Go to https://app.incident.io/settings/api-keys and create an API key with the following permissions: - "View data, like public incidents and organisation settings" - "Create incidents" - "Edit incidents" - "View all incident data, including private incidents" Copy the generated API key. ### 2. Configure Connection Go to {{ site.ui_url }}/settings/connections and create a new HTTP connection with: **Base URL:** ``` https://api.incident.io ``` **Allowed Routes:** ``` GET /v2/incidents POST /v2/incidents GET /v2/incidents/{id} POST /v2/incidents/{id}/actions/edit GET /v1/severities GET /v1/severities/{id} GET /v1/incident_statuses GET /v1/incident_statuses/{id} ``` **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` Replace `` with the API key you copied from step 1. ### 3. Add Description In the Description field, paste the content from the markdown block below: ````markdown The incident.io Incidents API v2 provides endpoints to create, read, list, and edit incidents. Incidents are a core resource in incident.io, on which many other resources (actions, etc.) are created. ## Available Operations ### 1. List Incidents **Purpose:** Retrieve a paginated list of all incidents for an organization with advanced filtering capabilities. **Query Parameters:** - `page_size` (integer, optional): Number of records to return (default: 25, max: 500) - `after` (string, optional): Incident ID for pagination - returns incidents after this ID - `status` (object, optional): Filter by incident status ID - Operators: `one_of`, `not_in` - Example: `status[one_of]=01GBSQF3FHF7FWZQNWGHAVQ804` - `status_category` (object, optional): Filter by status category - Operators: `one_of`, `not_in` - Values: `triage`, `declined`, `merged`, `canceled`, `live`, `learning`, `closed` - Example: `status_category[one_of]=live` - `created_at` (object, optional): Filter by creation timestamp - Operators: `gte` (greater than or equal), `lte` (less than or equal), `date_range` - Format: ISO date (YYYY-MM-DD) - Example: `created_at[gte]=2024-05-01` - Date range example: `created_at[date_range]=2024-12-02~2024-12-08` - `updated_at` (object, optional): Filter by last update timestamp - Operators: `gte`, `lte`, `date_range` - Format: ISO date (YYYY-MM-DD) - Example: `updated_at[lte]=2024-12-31` - `severity` (object, optional): Filter by severity ID or rank - Operators: `one_of`, `not_in`, `gte`, `lte` - Example: `severity[gte]=01GBSQF3FHF7FWZQNWGHAVQ804` - `incident_type` (object, optional): Filter by incident type ID - Operators: `one_of`, `not_in` - Example: `incident_type[one_of]=01GBSQF3FHF7FWZQNWGHAVQ804` - `incident_role` (object, optional): Filter by incident role assignment status - Operators: `one_of`, `is_blank` - Format: `incident_role[ROLE_ID][operator]=value` - Example: `incident_role[01GBSQF3FHF7FWZQNWGHAVQ804][is_set]=true` - `custom_field` (object, optional): Filter by custom field values - Operators vary by field type - Format: `custom_field[FIELD_ID][operator]=value` - Example: `custom_field[01GBSQF3FHF7FWZQNWGHAVQ804][one_of]=XYZ` - `mode` (object, optional): Filter by incident mode - Operator: `one_of` - Values: `standard`, `retrospective`, `test`, `tutorial` - Default: `{"one_of": ["standard", "retrospective"]}` (excludes test and tutorial) - Example: `mode[one_of]=retrospective` **Important Notes:** - All query parameters must be URI encoded - Multiple filters can be combined (incidents must match ALL filters) - Maximum page size is 250 - By default, test and tutorial incidents are excluded unless explicitly requested via `mode` filter **Response:** ```json { "incidents": [ { "id": "01FDAG4SAP5TYPT98WGR2N7W91", "reference": "INC-123", "name": "Our database is sad", "summary": "Our database is really really sad, and we don't know why yet.", "status": {...}, "severity": {...}, "incident_type": {...}, "mode": "standard", "visibility": "public", "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z", "slack_channel_id": "C02AW36C1M5", "slack_channel_name": "inc-165-green-parrot", "permalink": "https://app.incident.io/incidents/123" } ], "pagination_meta": { "after": "01FCNDV6P870EA6S7TK1DSYDG0", "page_size": 25, "total_record_count": 238 } } ``` **Example Request:** ```json { "method": "GET", "path": "/v2/incidents", "query_params": { "status_category[one_of]": "live", "page_size": "25" } } ``` --- ### 2. Create Incident **Purpose:** Create a new incident. When mode is set to "retrospective", the incident will not be announced in Slack. **Request Body Fields:** Required fields: - `idempotency_key` (string, required): Unique string to prevent duplicate incident creation - `visibility` (string, required): Incident visibility - `public` (open to all in Slack workspace) or `private` (invite-only) Optional fields: - `name` (string): Short explanation/title of the incident - `summary` (string): Detailed description of the incident - `severity_id` (string): ID of the severity level to assign - `incident_type_id` (string): ID of the incident type - `incident_status_id` (string): ID of the status to assign - `mode` (string): Incident mode - `standard`, `retrospective`, `test`, or `tutorial` - `slack_team_id` (string): Slack Team ID to create the incident in - `slack_channel_name_override` (string): Custom name for the Slack channel - `custom_field_entries` (array): Array of custom field values - Each entry contains: - `custom_field_id` (string): ID of the custom field - `values` (array): Array of value objects with appropriate value type fields - `incident_role_assignments` (array): Array of role assignments - Each assignment contains: - `incident_role_id` (string): ID of the role - `assignee` (object): Can specify by `id`, `email`, or `slack_user_id` - `incident_timestamp_values` (array): Array of timestamp values - Each value contains: - `incident_timestamp_id` (string): ID of the timestamp field - `value` (string): ISO 8601 timestamp - `retrospective_incident_options` (object): Options for retrospective incidents - `slack_channel_id` (string): Existing Slack channel ID - `postmortem_document_url` (string): URL to postmortem document - `external_id` (integer): External reference ID **Response:** ```json { "incident": { "id": "01FDAG4SAP5TYPT98WGR2N7W91", "reference": "INC-123", "name": "Our database is sad", "summary": "Our database is really really sad, and we don't know why yet.", "mode": "standard", "visibility": "public", "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z", "permalink": "https://app.incident.io/incidents/123", ... } } ``` **Example Request:** ```json { "method": "POST", "path": "/v2/incidents", "body": "{\"idempotency_key\": \"alert-uuid-12345\", \"name\": \"Database connection pool exhausted\", \"summary\": \"Production database connection pool has reached capacity\", \"severity_id\": \"01FH5TZRWMNAFB0DZ23FD1TV96\", \"incident_type_id\": \"01FH5TZRWMNAFB0DZ23FD1TV96\", \"mode\": \"standard\", \"visibility\": \"public\"}" } ``` --- ### 3. Get Incident (Show) **Purpose:** Retrieve a single incident by its ID or reference number. **Path Parameters:** - `id` (string, required): The incident's full ID (e.g., `01FDAG4SAP5TYPT98WGR2N7W91`) OR the numeric part of its reference (e.g., `123` for incident `INC-123`) **Response:** ```json { "incident": { "id": "01FDAG4SAP5TYPT98WGR2N7W91", "reference": "INC-123", "name": "Our database is sad", "summary": "Our database is really really sad, and we don't know why yet.", "call_url": "https://zoom.us/foo", "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z", "creator": {...}, "custom_field_entries": [...], "incident_role_assignments": [...], "incident_status": {...}, "incident_timestamp_values": [...], "incident_type": {...}, "severity": {...}, "mode": "standard", "visibility": "public", "slack_channel_id": "C02AW36C1M5", "slack_channel_name": "inc-165-green-parrot", "slack_team_id": "T02A1FSLE8J", "permalink": "https://app.incident.io/incidents/123", "postmortem_document_url": "https://docs.google.com/my_doc_id", "has_debrief": false, "workload_minutes_total": 60.7, "workload_minutes_working": 20, "workload_minutes_sleeping": 0, "workload_minutes_late": 40.7 } } ``` **Example Requests:** ```json { "method": "GET", "path": "/v2/incidents/01FDAG4SAP5TYPT98WGR2N7W91" } ``` ```json { "method": "GET", "path": "/v2/incidents/123" } ``` --- ### 4. Edit Incident **Purpose:** Edit properties of an existing incident such as severity, status, custom fields, role assignments, etc. Only provided fields will be updated (omitted fields are ignored). **Path Parameters:** - `id` (string, required): The unique identifier of the incident to edit **Request Body Fields:** Required fields: - `incident` (object, required): Object containing fields to update - `notify_incident_channel` (boolean, required): Whether to send Slack notifications about the update (won't work if channel is archived) The `incident` object can contain any of these optional fields: - `name` (string): Updated incident name - `summary` (string): Updated incident summary - `severity_id` (string): New severity ID - `incident_status_id` (string): New status ID - `call_url` (string): Video call URL for the incident - `slack_channel_name_override` (string): Override Slack channel name - `custom_field_entries` (array): Update custom field values (same structure as create) - `incident_role_assignments` (array): Update role assignments (same structure as create) - `incident_timestamp_values` (array): Update timestamp values (same structure as create) **Response:** ```json { "incident": { "id": "01FDAG4SAP5TYPT98WGR2N7W91", "reference": "INC-123", "name": "Our database is sad", "summary": "Our database is really really sad, and we don't know why yet.", ... } } ``` **Example Request:** ```json { "method": "POST", "path": "/v2/incidents/01FDAG4SAP5TYPT98WGR2N7W91/actions/edit", "body": "{\"incident\": {\"severity_id\": \"01G0J1EXE7AXZ2C93K61WBPYEH\", \"summary\": \"Database connection pool exhausted - identified root cause in connection timeout config\"}, \"notify_incident_channel\": true}" } ``` --- ### 5. List Severities **Purpose:** Retrieve all incident severities configured for the organization. Severities are required when creating incidents and help categorize incidents by urgency/impact. **Response:** ```json { "severities": [ { "id": "01FCNDV6P870EA6S7TK1DSYDG0", "name": "Minor", "description": "Issues with **low impact**.", "rank": 1, "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z" } ] } ``` **Example Request:** ```json { "method": "GET", "path": "/v1/severities" } ``` --- ### 6. Get Severity **Purpose:** Retrieve a single severity by its ID. **Path Parameters:** - `id` (string, required): Unique identifier of the severity **Response:** ```json { "severity": { "id": "01FCNDV6P870EA6S7TK1DSYDG0", "name": "Minor", "description": "Issues with **low impact**.", "rank": 1, "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z" } } ``` **Example Request:** ```json { "method": "GET", "path": "/v1/severities/01FCNDV6P870EA6S7TK1DSYDG0" } ``` --- ### 7. List Incident Statuses **Purpose:** Retrieve all incident statuses configured for the organization. Statuses are required when creating or editing incidents and help communicate where an incident is in its lifecycle. **Response:** ```json { "incident_statuses": [ { "id": "01FCNDV6P870EA6S7TK1DSYD5H", "name": "Closed", "description": "Impact has been **fully mitigated**, and we're ready to learn from this incident.", "category": "triage", "rank": 4, "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z" } ] } ``` **Important Notes:** - Status categories include: `triage`, `declined`, `merged`, `canceled`, `live`, `learning`, `closed` - Lower rank numbers appear first in lists - The `triage` and `declined` statuses are special and cannot be modified **Example Request:** ```json { "method": "GET", "path": "/v1/incident_statuses" } ``` --- ### 8. Get Incident Status **Purpose:** Retrieve a single incident status by its ID. **Path Parameters:** - `id` (string, required): Unique identifier of the incident status **Response:** ```json { "incident_status": { "id": "01FCNDV6P870EA6S7TK1DSYD5H", "name": "Closed", "description": "Impact has been **fully mitigated**, and we're ready to learn from this incident.", "category": "triage", "rank": 4, "created_at": "2021-08-17T13:28:57.801578Z", "updated_at": "2021-08-17T13:28:57.801578Z" } } ``` **Example Request:** ```json { "method": "GET", "path": "/v1/incident_statuses/01FCNDV6P870EA6S7TK1DSYD5H" } ``` --- ## Best Practices 1. **Idempotency:** Always use unique `idempotency_key` values when creating incidents to prevent duplicates 2. **Avoid Automation Spam:** Be careful with automated incident creation - duplicate incidents can be distracting and impact reporting 3. **Pagination:** When listing incidents, use the `after` parameter with the last incident ID from `pagination_meta` to fetch the next page 4. **Filtering:** Combine multiple filters to narrow down incidents efficiently 5. **Partial Updates:** When editing, only include fields you want to change - omitted fields remain unchanged 6. **Reference Shortcuts:** You can use just the numeric part of an incident reference (e.g., `123` instead of full ID) when getting or editing incidents 7. **Retrospective Mode:** Use `mode: "retrospective"` when importing historical incidents to avoid Slack notifications 8. **URI Encoding:** Always URI encode query parameters, especially when using special characters or operators 9. **Severities and Statuses:** Always list available severities and statuses first before creating/editing incidents to ensure you're using valid IDs ```` ### Pylon Connections Pylon connections enable agents to create internal issues and look up customer accounts in Pylon. Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Overview [Pylon](https://usepylon.com) is a customer support platform. With this connection, agents can: - Create internal issues for escalation and tracking - Search for customer accounts by domain - Retrieve account details for context during investigations ## Setup Instructions ### 1. Generate a Pylon API Token 1. Log in to Pylon at [app.usepylon.com](https://app.usepylon.com) 2. Navigate to **Settings** > **API Tokens** 3. Click **Create API Token** 4. Name your token (e.g., "Firetiger Integration") 5. Copy and securely store the generated token See the [Pylon API Authentication docs](https://docs.usepylon.com/pylon-docs/developer/api/authentication) for details. ### 2. Create the Connection In the Firetiger UI, create a new Pylon connection with your API token. ## Connection Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | -------------------- | | `api_token` | string | Yes | Your Pylon API token | ## Agent Capabilities Once configured, agents can use the following tools: | Tool | Description | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | **CreateIssue** | Creates an internal issue in Pylon (not visible to customers). Supports title, HTML body, account linking, priority, and tags. | | **SearchAccounts** | Finds customer accounts by domain. | | **GetAccount** | Retrieves full details for a specific account. | | **ListAccounts** | Lists all accounts with pagination. | ## Description Field Use the description field to guide agents on when and how to use this connection, and where relevant, with any specific details about how your Pylon instance is structured. **Example**: ``` Pylon connection for internal issue creation and account lookups. Use cases: - Create internal issues when monitoring detects customer-impacting problems - Look up customer accounts by domain during investigations - Get account context for triage and escalation Note: Issues created are INTERNAL only (not visible to customers). ``` ## API Reference If creating connections via the API instead of the UI: ```json { "display_name": "Pylon - Internal Issues", "description": "Pylon connection for internal issue creation...", "connection_details": { "pylon": { "api_token": "pylon_api_xxxxxxxxxxxxx" } } } ``` ## Communications Connect Firetiger to messaging and email platforms. ### Slack # Firetiger App for Slack [Firetiger](https://www.firetiger.com) is an AI agent platform for production monitoring. Firetiger agents identify and fix problems in production by combining observability data, codebase understanding, and knowledge of your business. The Firetiger app for Slack connects your Slack workspace to Firetiger so that agents can send real-time notifications and alerts directly to your Slack channels. When an agent detects an issue, investigates a root cause, or deploys a fix, it can post updates to the channels you configure — keeping your team informed without leaving Slack. > **AI Disclaimer:** Firetiger uses AI agents to analyze observability data and generate insights. AI-generated content, including messages sent to Slack, may occasionally contain inaccurate or incomplete information. Users should verify critical findings independently. ## Installation 1. Navigate to **Integrations** in the Firetiger UI 2. Click **New Connection** 3. Select **Slack** as the connection type 4. Click **Install Slack App** 5. In the popup, select your Slack workspace and click **Allow** The connection will be created automatically with your workspace details. ## What Gets Created When you install the Firetiger app for Slack, Firetiger automatically creates a connection with: | Field | Value | |-------|-------| | `connection_id` | `slack-{workspace_id}` (e.g., `slack-t1234567890`) | | `display_name` | Your Slack workspace name | | `description` | `Slack workspace: {workspace_name}` | ## Permissions The Firetiger app for Slack requests the following permissions: | Scope | Purpose | |-------|---------| | `channels:read` | List available channels | | `channels:join` | Join public channels to send messages | | `chat:write` | Send messages to channels | | `chat:write.public` | Send messages to public channels without joining | | `team:read` | Get workspace information | | `users:read` | List users for mentions | ## Re-authorization To update permissions or reconnect a workspace: 1. Navigate to **Integrations** 2. Find your Slack connection 3. Click **Reconnect** or delete and recreate the connection Slack scopes are additive - re-authorizing adds new permissions without removing existing ones. ## Tools Slack connections enable the following agent tools: | Tool | Description | |------|-------------| | `slack-send-message` | Send messages to one or more Slack channels | ### slack-send-message Send notifications to Slack channels. Supports Slack's mrkdwn format for rich text. **Parameters:** | Parameter | Required | Description | |-----------|----------|-------------| | `connection` | Yes | The Slack connection to use | | `channels` | Yes | List of channel names or IDs (e.g., `["#alerts", "C1234567890"]`) | | `message` | Yes | Message content (use Slack mrkdwn: `*bold*`, `_italic_`, `` `code` ``) | | `title` | No | Optional title displayed as a bold header | | `investigation_url` | No | Optional URL to link back to an investigation | ## Description Field The `description` field helps agents understand when to use this Slack workspace. **Example**: ``` Primary workspace for engineering alerts. Use for: - Incident notifications → #incidents - Deployment updates → #deployments - Agent status updates → #firetiger-alerts ``` ## Best Practices - **Use descriptive workspace names** - Helps agents select the right workspace when multiple are connected - **Document channel conventions** - Include which channels to use for different alert types - **Limit to necessary workspaces** - Only connect workspaces that agents need to notify ## Privacy & Terms - [Privacy Policy](https://www.firetiger.com/privacy-policy) - [Terms of Service](https://www.firetiger.com/terms-of-service) - [Trust Center](https://trust.firetiger.com) ### SendGrid Event Webhooks Configure SendGrid Event Webhook following the [official documentation](https://www.twilio.com/docs/sendgrid/for-developers/tracking-events/getting-started-event-webhook). ## Endpoint `{{ site.ingest_url }}/sendgrid/` ## SendGrid Configuration 1. Go to **Settings** > **Mail Settings** > **Event Webhook** 2. Enter the Firetiger endpoint URL: `{{ site.ingest_url }}/sendgrid/` 3. Select the event types you want to capture 4. Enable the webhook ## Tables Each SendGrid event type is stored in its own table under `sendgrid/events/{event-type}`: | Event Type | Table | |------------|-------| | processed | `sendgrid/events/processed` | | delivered | `sendgrid/events/delivered` | | deferred | `sendgrid/events/deferred` | | bounce | `sendgrid/events/bounce` | | dropped | `sendgrid/events/dropped` | | open | `sendgrid/events/open` | | click | `sendgrid/events/click` | | spamreport | `sendgrid/events/spamreport` | | unsubscribe | `sendgrid/events/unsubscribe` | | group_unsubscribe | `sendgrid/events/group_unsubscribe` | | group_resubscribe | `sendgrid/events/group_resubscribe` | Tables are created automatically when the first event of that type is received. Schema inference automatically adapts to new fields from SendGrid. ## Example Query ```sql SELECT event.email, event.response, timestamp FROM "sendgrid/events/delivered" WHERE timestamp > '2024-01-01' ``` ### Google Postmaster Tools Connections Google Postmaster Tools connections enable agents to query email deliverability metrics for domains sending to Gmail users. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Overview Google Postmaster Tools provides insights into: - **Domain/IP Reputation** - How Gmail perceives your sending reputation - **Spam Rates** - Percentage of emails marked as spam by users - **Authentication** - SPF, DKIM, and DMARC success rates - **Encryption** - TLS usage for email transport - **Delivery Errors** - Common delivery issues and their frequency ## Prerequisites Before creating a Google Postmaster Tools connection, complete these setup steps: ### 1. Create a Google Cloud Project 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select an existing one ### 2. Enable the Postmaster Tools API 1. Go to [Enable Postmaster Tools API](https://console.cloud.google.com/flows/enableapi?apiid=gmailpostmastertools.googleapis.com) 2. Select your project and click **Enable** ### 3. Create a Service Account 1. Go to [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) 2. Click **Create Service Account** 3. Fill in: - **Name**: e.g., "Postmaster API Client" - **ID**: auto-generated - **Description**: "Service account for Postmaster Tools API access" 4. Click **Create and Continue**, then **Done** ### 4. Enable Domain-Wide Delegation 1. Click on the service account you created 2. Go to the **Details** tab 3. Click **Show Advanced Settings** 4. Under **Domain-wide delegation**, click **Enable Google Workspace Domain-wide Delegation** 5. Note the **Client ID** (a numeric ID like `123456789012345678901`) ### 5. Download Service Account Credentials 1. On the service account page, go to the **Keys** tab 2. Click **Add Key** → **Create new key** 3. Choose **JSON** format and click **Create** 4. Save the downloaded JSON file securely ### 6. Configure Domain-Wide Delegation in Google Workspace This step requires **Google Workspace Super Admin** access. 1. Go to [Google Workspace Admin Console](https://admin.google.com/) 2. Navigate to **Security** → **Access and data control** → **API controls** 3. Scroll to **Domain-wide delegation** → Click **Manage Domain Wide Delegation** 4. Click **Add new** 5. Fill in: - **Client ID**: The numeric Client ID from step 4 - **OAuth scopes**: `https://www.googleapis.com/auth/postmaster.readonly` 6. Click **Authorize** ### 7. Verify Postmaster Access The user you'll impersonate must have access to Postmaster Tools: 1. Go to [Gmail Postmaster Tools](https://postmaster.google.com/) 2. Sign in as the user who will be impersonated 3. Verify they can see the domains you want to query ## Connection Parameters ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `service_account_json` | string | The full contents of the service account JSON key file | | `impersonate_user` | string | Email of a user with access to Postmaster Tools (e.g., `admin@yourdomain.com`) | ## Available Tools Once configured, agents have access to two tools: ### ListDomains Lists all domains registered in the Postmaster Tools dashboard. **Use this to**: Discover which domains are available for querying. **Returns**: Domain names and permission levels (OWNER/READER). ### GetTrafficStats Retrieves daily traffic statistics for a domain. **Parameters**: - `domain` (required): The domain to query (e.g., `example.com`) - `start_date` (optional): Start date in YYYY-MM-DD format (defaults to 7 days ago) - `end_date` (optional): End date in YYYY-MM-DD format (defaults to today) **Returns**: - Domain reputation (HIGH, MEDIUM, LOW, BAD) - IP reputations with sample IPs - User-reported spam ratio - SPF/DKIM/DMARC success rates - Encryption ratios (inbound/outbound TLS) - Delivery errors by type ## Description Field Document the domains and use cases for the connection. **Example**: ``` Google Postmaster Tools for monitoring email deliverability to Gmail. Available domains: - example.com - Primary marketing domain - transactional.example.com - Transactional email domain Use this connection to: - Check domain/IP reputation after email campaigns - Investigate spam complaints or delivery issues - Monitor authentication (SPF, DKIM, DMARC) success rates - Track encryption compliance Note: Google requires sufficient email volume for metrics to be available. Domains with low Gmail volume may not show statistics. ``` ## Example Connection ```json { "display_name": "Postmaster Tools - Example Corp", "description": "Google Postmaster Tools for monitoring email deliverability...", "connection_details": { "google_postmaster": { "service_account_json": "{\"type\": \"service_account\", \"project_id\": \"your-project\", ...}", "impersonate_user": "admin@example.com" } } } ``` ## Troubleshooting ### "Not authorized to access this resource" - Verify domain-wide delegation is configured with the correct Client ID - Check that the scope `https://www.googleapis.com/auth/postmaster.readonly` is authorized - Ensure the impersonate_user has access to Postmaster Tools ### "No domains found" - The impersonated user must have verified domains at https://postmaster.google.com/ - Domain verification requires adding DNS records (follow Google's instructions) ### "No traffic statistics available" Google requires sufficient email volume to display statistics. This can happen if: - The domain has low email volume to Gmail users - The date range has no email activity - The domain was recently verified ### API returns 403 - Verify the Postmaster Tools API is enabled in your Google Cloud project - Check that domain-wide delegation is properly configured ## Best Practices - **Use a dedicated service account** - Create a separate service account for Postmaster Tools access - **Impersonate an admin user** - The impersonated user should have access to all domains you need to query - **Monitor regularly** - Set up regular checks for reputation changes or spam spikes - **Document domains** - List available domains in the description field for agent context ## API Version This integration uses the Google Postmaster Tools API v1 (stable). Future versions may add support for v2beta features including compliance status and batch queries. ## Observability Forward telemetry data from observability tools into Firetiger. ### Vector # Configure Vector to send logs, metrics, or traces to Firetiger Vector can send data to Firetiger using the generic HTTP sink with the `/datapoints/` endpoint. Each sink writes to a separate Firetiger table based on the URL path, and Vector's template syntax lets you route data dynamically. ## Configuration Steps In your Vector configuration file(s) (`vector.toml`), add a new HTTP sink using the configuration provided below. Within the `inputs` array, specify your source names (e.g., `["system_logs", "application_logs"]`). ### Static table name Route all events from a sink to a single table: ```toml [sinks.firetiger] type = "http" inputs = ["..."] # add your sources here encoding.codec = "json" uri = "{{ site.ingest_url }}/datapoints/vector/logs" method = "post" healthcheck = false compression = "zstd" [sinks.firetiger.auth] strategy = "basic" user = "{{ site.ingest_username }}" password = "{{ site.ingest_password }}" ``` This sends all events to the `datapoints/vector/logs` table. ### Dynamic table name using Vector templates Use Vector's [template syntax](https://vector.dev/docs/reference/configuration/template-syntax/) to route events to different tables based on event fields: ```toml [sinks.firetiger] type = "http" inputs = ["..."] encoding.codec = "json" uri = "{{ site.ingest_url }}/datapoints/vector/{% raw %}{{ source_type }}{% endraw %}" method = "post" healthcheck = false compression = "zstd" [sinks.firetiger.auth] strategy = "basic" user = "{{ site.ingest_username }}" password = "{{ site.ingest_password }}" ``` This creates a separate table per source type (e.g., `datapoints/vector/file`, `datapoints/vector/syslog`). ## Supported Formats The `/datapoints/` endpoint accepts: - **JSON array**: `[{"key": "value"}, ...]` - **JSONL / NDJSON**: One JSON object per line (use `Content-Type: application/jsonl`) - **Single JSON object**: Automatically detected as JSONL Vector's `encoding.codec = "json"` sends events as JSON arrays, which is the recommended format. Compression (`gzip`, `zstd`, `deflate`, `snappy`) is supported via the `Content-Encoding` header. ## Authentication Firetiger expects basic auth for ingestion. Use the same ingest secrets shared with you for use with OpenTelemetry collectors etc to authenticate with the Vector ingest endpoint. ### Datadog Agent # Forward Traces and Metrics from a Datadog Agent to Firetiger This guide covers configuring a Datadog Agent to forward APM traces and metrics to Firetiger, where they are converted to OpenTelemetry format and stored in Iceberg. For log forwarding, see [DataDog Log Forwarding](datadog-forward.txt). ## Prerequisites - An active Firetiger deployment - Datadog Agent v7+ running in your environment - Firetiger credentials from the **Data Connections** page Your Firetiger ingest endpoint for Datadog data is: ``` {{ site.ingest_url }}/datadog ``` ## Step 1: Build your Firetiger API key 1. Log in to your Firetiger account 2. Navigate to **Data Connections → OpenTelemetry** 3. Note the **Username** and **Password** shown on the page The Datadog Agent takes a single `DD_API_KEY` string, so you need to combine the username and password into one Base64 token: ```bash # Linux / macOS echo -n 'USERNAME:PASSWORD' | base64 ``` Replace `USERNAME` and `PASSWORD` with the values from the Data Connections page. Use the resulting Base64 string wherever `` appears below. ## Option A: Firetiger Only Replace the Datadog backend entirely. All trace and/or metric data flows to Firetiger. The Datadog Agent treats API key values as opaque strings, so the Firetiger token works without issues. ### Traces only ```bash DD_API_KEY= DD_APM_DD_URL={{ site.ingest_url }}/datadog ``` ### Metrics only ```bash DD_API_KEY= DD_DD_URL={{ site.ingest_url }}/datadog ``` ### Traces + Metrics ```bash DD_API_KEY= DD_APM_DD_URL={{ site.ingest_url }}/datadog DD_DD_URL={{ site.ingest_url }}/datadog ``` ## Option B: Dual-Write (Datadog + Firetiger) Keep sending data to Datadog AND add Firetiger as an additional destination. Your existing Datadog setup remains unchanged. The Datadog Agent natively supports additional endpoint variables -- a JSON map of `{url: [api_keys]}`. Each endpoint gets its own API key. The real Datadog key stays in `DD_API_KEY` for the primary destination. ### Traces only ```bash DD_API_KEY= DD_APM_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' ``` ### Metrics only ```bash DD_API_KEY= DD_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' ``` ### Traces + Metrics ```bash DD_API_KEY= DD_APM_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' DD_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' ``` `DD_APM_ADDITIONAL_ENDPOINTS` is used by APM trace forwarding, while `DD_ADDITIONAL_ENDPOINTS` is used by the metrics forwarder. ## Configuration Examples ### Docker (Firetiger Only -- Traces + Metrics) ```bash docker run -d \ -e DD_API_KEY="" \ -e DD_APM_DD_URL="{{ site.ingest_url }}/datadog" \ -e DD_DD_URL="{{ site.ingest_url }}/datadog" \ -e DD_APM_ENABLED=true \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /proc/:/host/proc/:ro \ -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \ gcr.io/datadoghq/agent:7 ``` ### Docker (Dual-Write -- Traces + Metrics) ```bash docker run -d \ -e DD_API_KEY="" \ -e DD_APM_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' \ -e DD_ADDITIONAL_ENDPOINTS='{"{{ site.ingest_url }}/datadog": [""]}' \ -e DD_APM_ENABLED=true \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /proc/:/host/proc/:ro \ -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \ gcr.io/datadoghq/agent:7 ``` ### Docker Compose (Firetiger Only) ```yaml services: datadog-agent: image: gcr.io/datadoghq/agent:7 environment: DD_API_KEY: "" DD_APM_DD_URL: "{{ site.ingest_url }}/datadog" DD_DD_URL: "{{ site.ingest_url }}/datadog" DD_APM_ENABLED: "true" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /proc/:/host/proc/:ro - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro ``` ### Docker Compose (Dual-Write) ```yaml services: datadog-agent: image: gcr.io/datadoghq/agent:7 environment: DD_API_KEY: "" DD_APM_ADDITIONAL_ENDPOINTS: '{"{{ site.ingest_url }}/datadog": [""]}' DD_ADDITIONAL_ENDPOINTS: '{"{{ site.ingest_url }}/datadog": [""]}' DD_APM_ENABLED: "true" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /proc/:/host/proc/:ro - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro ``` ### Kubernetes Helm (Firetiger Only) In your `values.yaml` for the Datadog Helm chart: ```yaml datadog: apiKey: "" apm: portEnabled: true env: - name: DD_APM_DD_URL value: "{{ site.ingest_url }}/datadog" - name: DD_DD_URL value: "{{ site.ingest_url }}/datadog" ``` ### Kubernetes Helm (Dual-Write) ```yaml datadog: apiKey: "" apm: portEnabled: true env: - name: DD_APM_ADDITIONAL_ENDPOINTS value: '{"{{ site.ingest_url }}/datadog": [""]}' - name: DD_ADDITIONAL_ENDPOINTS value: '{"{{ site.ingest_url }}/datadog": [""]}' ``` ### datadog.yaml (Firetiger Only) ```yaml api_key: "" apm_config: enabled: true apm_dd_url: "{{ site.ingest_url }}/datadog" dd_url: "{{ site.ingest_url }}/datadog" ``` ### datadog.yaml (Dual-Write) ```yaml api_key: "" apm_config: enabled: true additional_endpoints: "{{ site.ingest_url }}/datadog": - "" additional_endpoints: "{{ site.ingest_url }}/datadog": - "" ``` ## Verify 1. Restart the Datadog Agent after configuration changes 2. Check agent status: ```bash datadog-agent status ``` 3. Look for the APM section -- it should show your configured endpoint 4. Generate some traffic in your application 5. Log in to Firetiger and check for trace data under traces 6. Check for metric data under metrics -- it may take a few minutes for the agent to flush its first metric payload ## Troubleshooting **No trace data appearing in Firetiger?** - Verify the ingest endpoint URL matches `{{ site.ingest_url }}/datadog` - Check that APM is enabled on the agent (`DD_APM_ENABLED=true`) - Ensure your application is instrumented with a Datadog tracing library and sending traces to the agent - Check agent logs for connection errors: `datadog-agent status` or `docker logs ` **No metric data appearing in Firetiger?** - Confirm you set `DD_DD_URL` (Firetiger-only) or `DD_ADDITIONAL_ENDPOINTS` (dual-write) -- these are separate from the APM trace variables - Do not confuse `DD_ADDITIONAL_ENDPOINTS` (metrics) with `DD_APM_ADDITIONAL_ENDPOINTS` (traces) -- they control different forwarders - Metrics are batched by the agent and flushed periodically; wait at least 2 minutes after restarting the agent - For containerized agents, DogStatsD must be enabled if you want custom metrics (`DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true`) **Authentication errors (401)?** - Go to **Data Connections → OpenTelemetry** and verify your username and password - Re-run `echo -n 'USERNAME:PASSWORD' | base64` with the correct values - Ensure the Base64 token is copied exactly with no extra whitespace or quotes - Verify there are no escaping issues in your environment variables **Agent startup warnings about /api/v1/validate?** - These warnings are harmless and do not affect trace or metric delivery - Firetiger handles this endpoint for connectivity checks **Dual-write not working?** - Verify the JSON format of `DD_APM_ADDITIONAL_ENDPOINTS` / `DD_ADDITIONAL_ENDPOINTS` is correct - The value must be a JSON object mapping URL to an array of API keys - Check for proper escaping in your shell or YAML configuration ### DataDog Log Forwarding # Forward logs from DataDog to Firetiger This guide covers forwarding logs from Datadog to Firetiger via a custom log destination. For forwarding traces and metrics via the Datadog Agent, see [Datadog Agent](datadog.txt). ## Configuring a log forwarding custom destination Consult the DataDog docs here: [https://docs.datadoghq.com/logs/log_configuration/forwarding_custom_destinations/?tab=http](https://docs.datadoghq.com/logs/log_configuration/forwarding_custom_destinations/?tab=http) You’ll need three inputs from Firetiger, an ingest endpoint, username, and password (also known as an ingest secret). The ingest endpoint for DataDog is `{{ site.ingest_url }}/datadog/logs` Configure DataDog to use Basic auth, with username and secret provided to you by Firetiger. # Log message handling DataDog sends logs as JSON arrays: `[ { "date": "2025-08-20T06:01:07.323Z", "service": "auth-service", "host": "localhost", "attributes": { "level": "INFO", "service": "auth-service", "host": "localhost", "source": "python-log-generator", "timestamp": "2025-08-20T06:01:07.323115Z", "tags": "env:dev,version:1.0.0,service:web-server" }, "_id": "AZjGER5YAACoY1YER9GoqwZA", "message": "Authentication token validated", "status": "info", "tags": ["source:undefined", "datadog.submission_auth:api_key"] } ]` This log will be ingested with: - Service: `auth-service` - Host: `localhost` - Timestamp: `2025-08-20T06:01:07.323115Z` - Severity: INFO - Message: "Authentication token validated" - Tags parsed as attributes ## Timestamp handling Firetiger processes timestamps with the following priority: 1. **`attributes.timestamp`** - Primary timestamp source (RFC3339 format) 2. **`date`** - Used as observed timestamp and fallback for record timestamp Both timestamps are preserved to maintain log timing accuracy. ## Severity mapping DataDog severity levels are automatically converted: - `DEBUG`, `debug` → DEBUG - `INFO`, `info` → INFO - `WARN`, `warn`, `WARNING`, `warning` → WARN - `ERROR`, `error` → ERROR - `FATAL`, `fatal`, `CRITICAL`, `critical` → FATAL ## Custom Build custom integrations with Firetiger using HTTP APIs and MCP servers. ### HTTP Connections HTTP connections enable agents to interact with RESTful APIs and web services. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## Connection Parameters An HTTP connection requires the following configuration: ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `base_url` | string | Base URL including scheme, host, and optional base path (e.g., `https://api.example.com/v1`) | | `allowed_routes` | string[] | List of route patterns that agents can access (see Route Patterns below) | ### Optional Parameters | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `headers` | map | Non-auth headers to include in all requests (e.g. `Content-Type`, `X-Tenant-ID`) | None | | `max_response_size_bytes` | int64 | Maximum response body size in bytes | 10MB (10485760) | | `timeout_seconds` | int32 | Request timeout in seconds | 30 seconds | ### Important Notes - **HTTPS Required**: The `base_url` must use HTTPS (not HTTP) for security. HTTP URLs will be rejected. - **Maximum Limits**: - `max_response_size_bytes` cannot exceed 10MB (10485760 bytes) - `timeout_seconds` cannot exceed 300 seconds (5 minutes) ## Route Patterns The `allowed_routes` parameter controls which endpoints agents can access. Uses [http.ServeMux syntax](https://pkg.go.dev/net/http#ServeMux). **Pattern types**: ```json "allowed_routes": [ "GET /api/status", // Exact match "GET /api/users/", // Prefix match (trailing slash) "GET /api/users/{id}", // Wildcard (single segment) "GET /files/{path...}" // Wildcard (remaining segments) ] ``` Supported methods: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` ## Authentication Authentication is configured via the `auth` oneof — set exactly one of the following methods. ### OAuth Client Credentials Automatically obtains and refreshes an OAuth 2.0 access token using the client credentials grant. The token is injected as an `Authorization: Bearer` header on each request. ```json "oauth_client_credentials": { "token_url": "https://auth.example.com/oauth/token", "client_id": "my-client-id", "client_secret": "my-client-secret", "scopes": "api.read api.write", "extra_params": { "audience": "https://api.example.com" } } ``` ### Bearer Token A static Bearer token sent as `Authorization: Bearer `. ```json "bearer_token": { "token": "sk-your-token" } ``` ### Basic Auth HTTP Basic authentication with username and password. ```json "basic_auth": { "username": "user", "password": "pass" } ``` ### Static Headers Raw auth headers included in every request. Use this when the API requires a custom auth header format. ```json "static_headers": { "headers": { "Authorization": "Bearer sk-your-token", "X-API-Key": "your-key" } } ``` Non-auth `headers` (in the top-level connection details) can be used alongside any auth method for headers like `Content-Type` or `X-Tenant-ID`. ## Description Field Document the API endpoints and usage patterns. **Example**: ``` Databricks API for cluster management. Endpoints: - GET /api/2.0/clusters/list - List all clusters - GET /api/2.0/clusters/get?cluster_id= - Get cluster details - POST /api/2.0/clusters/start - Start cluster (body: {"cluster_id": "..."}) - POST /api/2.0/clusters/terminate - Stop cluster (body: {"cluster_id": "..."}) Response format: JSON Rate limit: 30 req/min ``` ## Example Connection ```json { "display_name": "Databricks API", "description": "Databricks API for cluster management...", "connection_details": { "http": { "base_url": "https://api.databricks.com", "allowed_routes": [ "GET /api/2.0/clusters/list", "GET /api/2.0/clusters/get", "POST /api/2.0/clusters/start" ], "bearer_token": { "token": "dapi123..." }, "max_response_size_bytes": 5242880, "timeout_seconds": 30 } } } ``` ## Best Practices - **Least privilege** - Only include necessary routes in `allowed_routes` - **Document endpoints** - List available endpoints and response formats in description - **Include rate limits** - Document API rate limits in the description - **HTTPS required** - All connections must use HTTPS - **Prefer OAuth** - Use OAuth Client Credentials when the API supports it for automatic token refresh ### MCP Servers # MCP Server Connections MCP (Model Context Protocol) connections enable agents to access tools from external services like GitHub, Linear, Notion, and more. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/integrations/mcp` ## What is MCP? The [Model Context Protocol](https://modelcontextprotocol.io/) is an open standard that allows AI agents to securely connect to external tools and data sources. MCP servers expose tools that agents can invoke to perform actions like creating issues, querying databases, or sending notifications. ## Installation 1. Navigate to **Settings > MCP Servers** in the Firetiger UI 2. Click **Connect Server** 3. Either: - Select a **suggested server** (GitHub, Linear, Notion, Sentry, Atlassian, PagerDuty) - Or enter a custom **Server URL** for any MCP-compatible server 4. Click **Connect** to initiate the OAuth flow 5. Authorize Firetiger to access the service in the popup The connection will be created automatically once authorization is complete. ## Suggested Servers Firetiger provides quick-connect options for popular MCP servers: | Service | URL | Description | |---------|-----|-------------| | GitHub Copilot | `https://api.githubcopilot.com/mcp/` | Access issues, PRs, and repositories | | Linear | `https://mcp.linear.app/mcp` | Manage issues and project tracking | | Notion | `https://mcp.notion.com/mcp` | Access pages, databases, and docs | | Sentry | `https://mcp.sentry.dev/sse` | Monitor errors and performance | | Atlassian | `https://mcp.atlassian.com/v1/sse` | Connect Jira, Confluence, and more | | PagerDuty | `https://mcp.pagerduty.com/mcp` | Manage incidents and on-call | ## What Gets Created When you connect an MCP server, Firetiger creates a connection with: | Field | Value | |-------|-------| | `connection_id` | Auto-generated unique identifier | | `server_url` | The MCP server URL you connected to | | `server_name` | Automatically fetched from the server metadata | | `display_name` | Customizable name (defaults to server name) | | `description` | Optional description for agent context | ## Viewing Available Tools After connecting, you can view the tools provided by the MCP server: 1. Navigate to **Settings > MCP Servers** 2. Click on the connection card 3. View the **Available Tools** section 4. Click **Refresh Tools** to update the tool list from the server Each tool displays its name, description, and input schema. ## Authentication MCP connections use OAuth 2.0 for secure authentication: - Firetiger never stores your credentials directly - Access tokens are securely managed and refreshed automatically - You can revoke access at any time from the connected service's settings ## Customization ### Display Name Set a descriptive display name to help identify the connection: ``` Production GitHub - Engineering Org ``` ### Description The description field helps agents understand when and how to use this connection: ``` GitHub connection for the engineering organization. Use for: - Creating and managing issues in product repos - Reviewing pull requests - Accessing repository documentation ``` ## Managing Connections ### Refresh Tools If the MCP server adds new tools, click **Refresh Tools** to update the available tool list. ### Delete Connection To remove an MCP connection: 1. Click on the connection card 2. Click **Delete Connection** 3. Confirm the deletion This revokes Firetiger's access and removes the connection. You can reconnect at any time. ## Custom MCP Servers You can connect any MCP-compatible server by entering its URL. The server must: - Implement the [MCP specification](https://modelcontextprotocol.io/) - Support OAuth 2.0 authentication - Be accessible from Firetiger's infrastructure ## Best Practices - **Use descriptive names** - Help agents identify the right connection when multiple are available - **Document tool usage** - Include guidance on which tools to use for different scenarios - **Limit connections** - Only connect services that agents need access to - **Review permissions** - Understand what access each MCP server requests before connecting ### OpenAPI Connections OpenAPI connections let agents interact with any REST API that publishes an OpenAPI (Swagger) specification. Agents can introspect the spec to discover available endpoints and make authenticated requests. **Recommended**: Create and manage connections via the web UI at `{{ site.ui_url }}/settings/connections` ## When to use OpenAPI vs HTTP | | OpenAPI | HTTP | |:--|:--------|:-----| | **Endpoint discovery** | Agents read the spec to find endpoints | You list endpoints in the description | | **Route restrictions** | Requests are validated against the server domain | You configure explicit `allowed_routes` | | **Best for** | APIs with published OpenAPI specs | APIs without specs, or when you need fine-grained route control | ## Connection Parameters ### Required Parameters | Parameter | Type | Description | |-----------|------|-------------| | `spec_url` | string | URL to fetch the OpenAPI specification (JSON or YAML) | ### Optional Parameters | Parameter | Type | Description | |-----------|------|-------------| | `server_url` | string | Base URL of the API server. If omitted, derived from the spec's `servers[0].url` | ## Authentication Authentication is configured via the `auth` oneof — set exactly one of the following methods. These reuse the same auth types as [HTTP connections](http.txt#authentication). ### OAuth Client Credentials Automatically obtains and refreshes an OAuth 2.0 access token using the client credentials grant. ```json "oauth_client_credentials": { "token_url": "https://app.example.com/oauth/token", "client_id": "my-client-id", "client_secret": "my-client-secret", "scopes": "api.all:read" } ``` ### Bearer Token A static Bearer token sent as `Authorization: Bearer `. ```json "bearer_token": { "token": "sk-your-token" } ``` ### Basic Auth HTTP Basic authentication with username and password. ```json "basic_auth": { "username": "user", "password": "pass" } ``` ## Agent Tools OpenAPI connections provide two tools to agents: ### `openapi_schema` Introspects the OpenAPI spec. With no path, returns a summary of all available endpoints. With a path (e.g. `/users`), returns the full schema including parameters, request body, and response schemas. ### `openapi_request` Makes an HTTP request to the API. The agent provides a full URL (e.g. `https://api.example.com/v1/users`), which is validated against the configured server domain to prevent credential leakage. ## Server URL Resolution When `server_url` is omitted, the server URL is resolved from the spec: 1. The spec is fetched from `spec_url` 2. `servers[0].url` is extracted 3. If the server URL is relative (e.g. `/v1`), it is resolved against the spec URL For example, a spec at `https://api.example.com/openapi.json` with `servers: [{url: "/v1"}]` resolves to `https://api.example.com/v1`. ## Example Connection ```json { "display_name": "Vanta API", "description": "Vanta compliance platform API", "connection_details": { "openapi": { "spec_url": "https://firetiger-public.s3.us-west-2.amazonaws.com/connections/vanta/openapi.json", "server_url": "https://api.vanta.com/v1", "oauth_client_credentials": { "token_url": "https://api.vanta.com/oauth/token", "client_id": "my-client-id", "client_secret": "my-client-secret", "scopes": "vanta-api.all:read" } } } } ``` ## Best Practices - **Prefer OAuth** - Use OAuth Client Credentials when the API supports it for automatic token refresh - **Set server_url explicitly** - While it can be derived from the spec, setting it explicitly avoids extra network calls - **Use openapi_schema first** - Agents should introspect the spec before making requests to understand available endpoints and parameters ## Networking Configure network connectivity between Firetiger deployments and your infrastructure. ### AWS VPC Peering VPC peering enables Firetiger agents to connect to resources hosted in your AWS VPC, such as RDS databases, Elasticsearch clusters, or other private services. > VPC peering is only available for [BYOC (Bring Your Own Cloud)](/deploy/aws.txt) deployments. SaaS deployments use public endpoints or [AWS connections](/integrations/infrastructure/aws.txt) instead. ## How It Works A VPC peering connection creates a private network link between the Firetiger deployment VPC and your VPC. Traffic between the two VPCs stays within the AWS network and does not traverse the public internet. ## Prerequisites - A [BYOC AWS deployment](/deploy/aws.txt) provisioned by Firetiger - Your VPC must be in the same AWS region as the Firetiger deployment - VPC CIDR ranges must not overlap (Firetiger deployments typically use `10.0.0.0/16`) ## Setup ### 1. Create the VPC Peering Connection From your AWS account, create a VPC peering connection request: - **Requester VPC**: Your VPC (where your resources live) - **Accepter VPC**: The Firetiger deployment VPC (ID provided by Firetiger) - **Accepter AWS Account ID**: Provided by Firetiger - **Region**: Must match the Firetiger deployment region ### 2. Accept the Peering Connection Firetiger will accept the peering request from the deployment AWS account. ### 3. Enable DNS Resolution (if needed) If your resources use private DNS hostnames (e.g., RDS endpoints like `mydb.abc123.us-east-1.rds.amazonaws.com`), enable DNS resolution on both sides of the peering connection. ### 4. Configure Your Side In **your** AWS account, add: - **Route table entry**: Route the Firetiger VPC CIDR (e.g., `10.0.0.0/16`) to the peering connection - **Security group rule**: Allow inbound traffic from the Firetiger VPC CIDR on the required port (e.g., PostgreSQL 5432, MySQL 3306) ### 5. Provide Peering Details to Firetiger Send the following information to your Firetiger contact: | Field | Example | Description | |---|---|---| | VPC Peering Connection ID | `pcx-034daeb7643728bd9` | The peering connection ID after acceptance | | Your VPC CIDR | `172.30.0.0/16` | The CIDR range of your VPC that needs to be routable | | DNS resolution needed | Yes / No | Whether private DNS hostnames need to resolve across the peering | Firetiger will add the peering route to the deployment's Terraform configuration and apply it. ## Verification Once both sides are configured, test the connection from the Firetiger UI by running an agent that connects to your resource. If the agent can reach the target endpoint, the peering is working correctly. ## Troubleshooting ### Connection to your resource times out (but other agent functions work) - Verify your security group allows inbound traffic from the Firetiger VPC CIDR - Verify your route table has a return route to the Firetiger VPC CIDR via the peering connection - Check that the peering connection status is **Active** in the AWS console ### DNS resolution fails for RDS or other private endpoints - Ensure DNS resolution is enabled on the peering connection (both requester and accepter sides) - This setting is found under the peering connection's DNS tab in the AWS console ### All agent invocations time out This is not a peering issue. Contact Firetiger support - the deployment's NAT gateway route may need attention. ## Important Notes - **Do not modify Firetiger networking directly.** The Firetiger VPC's route tables, subnet associations, and NAT gateways are managed by Terraform. Manually modifying these resources will break Lambda internet connectivity and cause all agent invocations to fail. - Always coordinate through Firetiger to add peering routes to the deployment infrastructure. ### Network Transports Network Transports enable Firetiger to connect to databases and services on private networks that are not directly reachable from the public internet. When you create a [database connection](/integrations/databases/) that targets a host on a private network, you can attach a network transport to route traffic through a secure tunnel instead of attempting a direct connection over the public network. ## How It Works 1. You configure a **network transport** with credentials for a supported networking provider (e.g., Tailscale) 2. You create a **connection** and set its `network_transport` field to reference the transport 3. When an agent queries the connection, Firetiger's proxy server joins the private network on-demand and tunnels the connection traffic through it ## Supported Providers | Provider | Description | | ---------------------------------------------------- | -------------------------------------------------------------------------- | | [Tailscale](/integrations/networking/tailscale.txt) | Connect to databases on a Tailscale tailnet using OAuth client credentials | ## Creating a Network Transport Network transports can be created via the UI: <{{ site.ui_url }}/integrations/network-transports> ```bash ftops api network-transports create --id --from-file transport.json ``` See the provider-specific documentation for the required configuration fields. ## Attaching a Transport to a Connection When creating or updating a database connection, set the `network_transport` field to reference the transport by name: ```json { "displayName": "Private Database", "description": "PostgreSQL database on private network", "connectionType": "CONNECTION_TYPE_POSTGRES", "networkTransport": "network-transports/", "connectionDetails": { "postgres": { "host": "db.internal.example.com", "port": 5432, "database": "mydb", "username": "firetiger", "password": "secret", "sslMode": "require" } } } ``` The agent will automatically route traffic through the network transport when querying this connection. #### Tailscale Network Transport Tailscale network transports enable Firetiger agents to connect to databases and services on your [Tailscale](https://tailscale.com) tailnet. This is useful when your data sources are on a private network accessible via Tailscale but not reachable from the public internet. ## How It Works 1. Create a Tailscale OAuth Client for Firetiger: 2. Create a Firetiger Network Transport with these OAuth Client Credentials: <{{ site.ui_url }}/integrations/network-transports> 3. Create a Firetiger Connection that uses this Tailscale Network Transport 4. The Connection's traffic will proxy through an ephemeral tailscale node, with the tailscale tag ACLs you configure The proxy node is ephemeral — it appears in your tailnet only while actively tunneling and is automatically cleaned up. ## Prerequisites - A [Tailscale](https://tailscale.com) account with admin access - The target database must be reachable from your tailnet (either running Tailscale directly, or behind a [subnet router](https://tailscale.com/kb/1019/subnets)) ## Setup ### Step 1: Define an ACL Tag Firetiger's proxy node needs an ACL tag to identify itself on your tailnet. Define a tag in your Tailscale ACL policy. 1. Go to [Access Controls](https://login.tailscale.com/admin/acls) in the Tailscale admin console 2. Add a tag to the `tagOwners` section: ```json "tagOwners": { "tag:firetiger": ["autogroup:admin"] } ``` ### Step 2: Grant Network Access In the same ACL policy, grant the tag permission to reach your database. Using grants: ```json "grants": [ { "src": ["tag:firetiger"], "dst": ["*"], "ip": ["5432"] } ] ``` This allows the `tag:firetiger` node to connect to any machine on your tailnet on port 5432 (PostgreSQL). Adjust `dst` and `ip` to match your security requirements: - Restrict `dst` to specific machines or tags (e.g., `["tag:databases"]`) - Restrict `ip` to the specific ports your databases use ### Step 3: Create an OAuth Client Firetiger uses Tailscale OAuth client credentials to authenticate and join your tailnet. 1. Go to [Settings > OAuth clients](https://login.tailscale.com/admin/settings/oauth) in the Tailscale admin console 2. Click **Generate OAuth client** 3. Configure the client: - **Description**: `firetiger` (or similar) - **Tags**: Select `tag:firetiger` - **Scopes**: Ensure `auth_keys` Write is included (this allows the client to generate auth keys with the selected tags) 4. Click **Generate** 5. Copy the **Client ID** and **Client Secret** — the secret is only shown once. > The OAuth client must have the `tag:firetiger` tag selected. Without it, the proxy cannot generate tagged auth keys and will fail with "requested tags are invalid or not permitted". ### Step 4: Create the Network Transport Create the network transport in Firetiger using the OAuth credentials from the previous step: 1. Navigate to <{{ site.ui_url }}/integrations/network-transports> 2. Create Network Transport > Tailscale 3. Enter your Tailscale OAuth Client connection details: | Field | Required | Description | | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `oauthClientId` | Yes | OAuth client ID from Step 3 | | `oauthClientSecret` | Yes | OAuth client secret from Step 3 | | `tailnet` | Yes | Your tailnet name (e.g., `example.ts.net`). Find it at [Settings > General](https://login.tailscale.com/admin/settings/general) or run `tailscale status --json | jq -r .MagicDNSSuffix` | | `tags` | Yes | ACL tags to assign to the proxy node. Must be a subset of the tags authorized on the OAuth client | | `hostname` | No | Custom hostname for the proxy node in your tailnet (default: auto-generated) | ### Step 5: Create a Connection Using the Transport 1. Create a Connection via <{{ site.ui_url }}/integrations/connections/new> 2. Select a Connection type (e.g. Postgres) 3. Under Network Transport, select your Tailscale Network Transport 4. Configure the Connection details The `host` should be the Tailscale hostname (e.g., `db-server`) or Tailscale IP address (e.g., `100.x.y.z`) of the machine running your database. If the database is behind a subnet router, use the private IP address that the subnet router advertises. Click Save + Test to verify that the connection is working. ## Troubleshooting ### "requested tags are invalid or not permitted" The OAuth client does not have the specified tags authorized. Go to [Settings > OAuth clients](https://login.tailscale.com/admin/settings/oauth), find your client, and verify it has `tag:firetiger` selected. ### "tailnet not found" The `tailnet` field has the wrong value. Find your tailnet name at [Settings > General](https://login.tailscale.com/admin/settings/general) or run: ```bash tailscale status --json | jq -r .MagicDNSSuffix ``` ### "tailnet-owned auth key must have tags set" The network transport was created without the `tags` field. Update it to include tags by updating the Network Transport ### Connection times out after transport is established - Verify the database host is reachable from your tailnet (try `tailscale ping ` from another tailnet node) - Check that your ACL grants allow the `tag:firetiger` tag to reach the database host and port - If the database is behind a subnet router, verify the subnet routes are approved in the Tailscale admin console --- # Deployment Options This section covers deploying and managing Firetiger in your infrastructure. ## Guides - [SaaS](saas.txt) - Firetiger's default hosted deployment option - [BYOC: AWS](aws.txt) - Deploy Firetiger to your AWS account - [BYOC: GCP](gcp.txt) - Deploy Firetiger to Google Cloud ## SaaS # Firetiger SaaS Firetiger SaaS is the default hosted option. Firetiger manages all infrastructure so you can start ingesting and querying telemetry data immediately. Get started at [firetiger.com](https://firetiger.com). ## BYOC: AWS # AWS Cross-Account Access Setup Guide This guide will walk you through the process of setting up cross-account access between your AWS account and the Firetiger AWS account (975050257559). This allows Firetiger to access resources in your AWS account in a secure and controlled manner. ## Account Requirements ### Dedicated sub-account Provision a standalone AWS sub-account in your AWS Organization for Firetiger. This account should not host unrelated workloads. ### No out-of-band modifications After granting Firetiger the deployment role, avoid modifying account-wide settings or Firetiger-managed resources without coordination. Contact your Firetiger Solutions Engineer to discuss changes. ### Baseline settings - AWS CloudTrail enabled for management events across all regions ## Creating Your AWS Account Follow this link to create an account on the AWS console: Click "Add an AWS account", then follow the steps to create a new account to deploy Firetiger in: ## Setting Up Cross-Account Access We've created a CloudFormation template to automatically provision the required permissions in your AWS account. **Step 1:** Save the following as `firetiger-bootstrap.json`: ```json { "Resources": { "CrossAccountAccessForFiretiger": { "Type": "AWS::IAM::Role", "DeletionPolicy": "Retain", "Properties": { "RoleName": "CrossAccountAccessForFiretiger", "Description": "Allows full administrative access from the Firetiger account", "ManagedPolicyArns": ["arn:aws:iam::aws:policy/AdministratorAccess"], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": ["arn:aws:iam::975050257559:root"] }, "Action": ["sts:AssumeRole"] } ] } } } }, "Outputs": { "RoleARN": { "Description": "ARN of the CrossAccountAccessForFiretiger role", "Value": { "Fn::GetAtt": ["CrossAccountAccessForFiretiger", "Arn"] } } } } ``` **Step 2:** Apply the CloudFormation template: ```bash aws cloudformation create-stack --stack-name firetiger-bootstrap \ --template-body file://firetiger-bootstrap.json \ --capabilities CAPABILITY_NAMED_IAM ``` **Step 3:** Wait for the stack to complete: ```bash aws cloudformation wait stack-create-complete --stack-name firetiger-bootstrap ``` **Step 4:** Retrieve the Role ARN: ```bash aws cloudformation describe-stacks --stack-name firetiger-bootstrap \ --query 'Stacks[0].Outputs[?OutputKey==`RoleARN`].OutputValue' \ --output text ``` Share this Role ARN with your Firetiger Solutions Engineer to complete the setup. ## What Firetiger will use this role for For your information, here's what we'll set up on our account (975050257559) to make this work: 1. Create an IAM policy that allows assuming your role 2. Attach this policy to the appropriate IAM roles in our account 3. Configure our systems to use these credentials to assume your role ### Example of the Firetiger IAM Policy used to assume your role We create a policy in our account that looks like this: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::YOUR_ACCOUNT_ID:role/CrossAccountAccessForFiretiger" } ] } ``` We then attach this policy to a deployment IAM Role used to provision resources into your account. ## Setting up Anthropic LLM access Firetiger uses Anthropic Claude models via Amazon Bedrock. Before these models can be invoked, you must complete a one-time setup in the AWS account that runs Firetiger. ### 1. Complete the Anthropic First Time Use (FTU) form Open the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/) → **Model catalog** → select any Anthropic Claude model. If this is the first time using Anthropic models in the account, you'll be prompted to fill out the FTU form. Use your company's name, website, and write "LLM access for Firetiger AI products" in the use case field. Access is granted immediately after submission. If the form does not appear, the FTU has already been completed for this account (or inherited from the AWS Organization management account) and no further action is needed for this step. ### 2. Required models Firetiger needs access to these Anthropic models: - **Claude Sonnet 4.5** — main model (global cross-region inference) - **Claude Haiku 4.5** — light model (regional cross-region inference) - **Claude Opus 4.5** — heavy model (regional cross-region inference) After the FTU form is complete, Bedrock auto-subscribes to each model on first invocation (may take up to 15 minutes). See [Amazon's model access documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.txt) for more details. ## Access Policy The following principles govern how Firetiger employees access your AWS account under the Managed BYOC model: 1. Purpose of the role: The deployment role is used by Firetiger automation to deploy and operate Firetiger resources in your account. 2. Account ownership: Your AWS account is owned and managed by you, the customer. Firetiger does not take ownership of your account. 3. Consent: Firetiger employees may assume the deployment role only with explicit customer consent for the specific access window and purpose. 4. Authentication and authorization: Firetiger employee access to AWS resources is managed via AWS SSO, with enforced multi‑factor authentication for all logins. 5. Auditability: All account activity is auditable via AWS CloudTrail. [CloudTrail should be enabled by default](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.txt) for new AWS Accounts. The customer is responsible for configuring it to meet organizational requirements. For more details on Firetiger's Access Policy and other controls, please visit or contact us ## BYOC: GCP # Deploy Firetiger to Google Cloud This document describes how to deploy Firetiger to a GCP project in your GCP organization. During this process, you will: 1. Create a new GCP Project configured with a Billing Account 2. Enable required service APIs within the project 3. Grant Firetiger permission to deploy the Firetiger stack in your new project # Prerequisites 1. You, the Firetiger customer, have access to the Google Cloud Console with permission to: - Create and Manage Projects (ie `roles/resourcemanager.projectCreator`) - Associate a project with a GCP Billing Account (ie `roles/billing.user`) - Enable APIs within the new project - Manage IAM permissions within the new project 2. [Google Cloud CLI installed (`gcloud`)](https://cloud.google.com/sdk/docs/install) # Setup First, we’ll ensure we have a GCP Project and that it is associated with a billing account: 1. Create a new project (if not using an existing one): ```bash # Create new project (optional - can use existing) export GCP_PROJECT_ID="firetiger-$company" gcloud projects create $GCP_PROJECT_ID --name="Firetiger" # Set the working project gcloud config set project $GCP_PROJECT_ID ``` 1. Associate the project with a Billing Account First, choose the relevant Billing Account for your GCP Organization. You can see your billing accounts by running: ```protobuf gcloud billing accounts list ``` Then, configure your billing account ID and link it to the new project ```bash export BILLING_ACCOUNT_ID="your-billing-account-id" gcloud billing projects link $GCP_PROJECT_ID --billing-account $BILLING_ACCOUNT_ID ``` 1. Enable Required Services in Your Project: ```bash # Enable services required by Firetiger gcloud --project $GCP_PROJECT_ID services enable \ aiplatform.googleapis.com \ artifactregistry.googleapis.com \ bigquery.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ cloudresourcemanager.googleapis.com \ cloudscheduler.googleapis.com \ eventarc.googleapis.com \ iam.googleapis.com \ logging.googleapis.com \ pubsub.googleapis.com \ run.googleapis.com \ secretmanager.googleapis.com \ sqladmin.googleapis.com \ storage.googleapis.com ``` 1. Grant Firetiger Permission to Deploy the Firetiger Stack to your project (via Service Account) ```bash export FIRETIGER_SA="deployer@firetiger-control-plane.iam.gserviceaccount.com" # Grant required permissions to the Firetiger Project gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="domain:firetiger.com" \ --role="roles/editor" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/editor" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/resourcemanager.projectIamAdmin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/secretmanager.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/run.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/artifactregistry.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/pubsub.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/storage.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/serviceusage.serviceUsageAdmin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/iam.serviceAccountUser" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/logging.configWriter" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/bigquery.admin" gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \ --member="serviceAccount:$FIRETIGER_SA" \ --role="roles/cloudfunctions.admin" ``` 1. Share your new GCP Project ID with your Firetiger point of contact ## Setting up Anthropic LLM access Firetiger uses Anthropic Claude models via Vertex AI. You must enable these models in your project's Model Garden before they can be invoked. 1. Open the [Vertex AI Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) in your project 2. Search for each of the following Anthropic Claude models and click **Enable** on each: - **Claude Sonnet 4.5** - **Claude Haiku 4.5** - **Claude Opus 4.5** 3. Accept the terms/EULA when prompted See [Google's Model Garden documentation](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-garden/use-models) for more details. # Next Steps Firetiger will set up resources in that project. They’ll add a bucket that will hold data, services that ingest and compact data, and credentials for access. They’ll give you connection info, which will include URLs for ingesting and querying data as well as credential sets. Firetiger can ingest data in multiple ways. Refer to the following documentation for instructions on how to send data to Firetiger: [Firetiger Integrations](../integrations/) # Additional Resources [How to Create Public Google Cloud Run Services When Domain Restricted Sharing is Enabled](https://www.notion.so/How-to-Create-Public-Google-Cloud-Run-Services-When-Domain-Restricted-Sharing-is-Enabled-1a570c7133b4800ea86bdf0a2446f29d?pvs=21) --- # Account Management Manage your Firetiger organization settings, authentication, and access controls. ## SSO # Single Sign-On (SSO) Configure SSO to allow your team to sign in to Firetiger using your organization's identity provider via SAML. ## Supported Providers - **[Google Workspace]({% link sso/google-workspace.md %})** - Set up SAML SSO with Google Workspace ### Google Workspace # Setup Google Workspace SSO This guide walks through configuring Google Workspace as a SAML identity provider for Firetiger. You will create a custom SAML app in the Google Admin Console and provide the resulting configuration to Firetiger. ## Prerequisites - Google Workspace admin access - Firetiger deployment with SSO enabled ## Step 1: Create a Custom SAML App 1. Sign in to the [Google Admin Console](https://admin.google.com) 2. In the left sidebar, go to **Apps** > **Web and mobile apps** 3. Click **Add app** > **Add custom SAML app** 4. Enter an **App name** (e.g., "Firetiger") and optionally upload an icon 5. Click **Continue** ## Step 2: Download Identity Provider Metadata On the **Google Identity Provider details** screen: 1. Click **Download Metadata** to download the IdP metadata XML file 2. Save this file -- you will provide it to Firetiger in a later step 3. Click **Continue** Alternatively, you can manually copy the **SSO URL**, **Entity ID**, and **Certificate** values from this screen. ## Step 3: Configure Service Provider Details Enter the values provided by Firetiger: | Field | Value | | ------------- | --------------------- | | **ACS URL** | Provided by Firetiger | | **Entity ID** | Provided by Firetiger | Under **Name ID**: 1. Set the **Name ID format** to **EMAIL** 2. Set the **Name ID** to **Basic Information > Primary email** Click **Continue**. ## Step 4: Configure Attribute Mapping In the **Attributes** section, click **Add mapping** to create the following mappings: | Google Directory Attribute | App Attribute | | -------------------------- | ------------- | | Primary email | `mail` | | First name | `firstName` | | Last name | `lastName` | Click **Finish**. ## Step 5: Enable the App for Users After creating the app, you will be on the app detail page: 1. In the **User access** section, click **OFF for everyone** 2. On the **Service status** page, select **ON for everyone** (or select specific organizational units) 3. Click **Save** Changes may take up to 24 hours to propagate, though they typically apply within a few minutes. ## Step 6: Provide Configuration to Firetiger Send the following to Firetiger to complete the setup: - The **IdP metadata XML file** downloaded in Step 2, or the individual **SSO URL**, **Entity ID**, and **Certificate** values Once Firetiger configures the connection, users in your Google Workspace organization will be able to sign in via SSO. ## API Keys API keys are programmatic access credentials for the Firetiger API. They're used to authenticate API calls like triggering [Agents](../concepts/agents.txt) via webhook, listing resources, or integrating with external systems. You can manage your API keys at **Settings > API keys**: ## Creating an API key Click **+ Create API key** to create a new credential. You'll be asked to provide: - **Name** — a label to help you remember what this key is for (e.g. `ci-deploy-trigger`, `datadog-forwarder`). - **Access level** — either **Read-only** or **Read-write**. Use read-only keys when possible to limit the blast radius of a leaked credential. After creation, the secret value is shown once. Copy it and store it securely — you won't be able to see it again. ## Access levels | Level | Can do | | :--- | :--- | | **Read-only** | List resources, read agent results | | **Read-write** | Everything above, plus trigger agents via webhook, create and modify resources | ## Using an API key API keys authenticate with HTTP Basic auth. When you create a key, the dialog provides a username, password, and a pre-computed `Authorization` header value you can use directly: ``` Authorization: Basic ``` For example, to trigger an agent via webhook: ```bash curl -X POST "{{ site.api_url }}/firetiger.agents.v1.AgentsService/TriggerAgent" \ -u "username:password" \ -H "Content-Type: application/json" \ -d '{"name": "agents/your-agent-id", "message": "deploy completed"}' ``` ## Revoking an API key Click the trash icon next to any key to revoke it. Revocation is immediate — any requests using that key will start failing right away. --- # API Reference This is the reference documentation for the Firetiger REST API. The API follows [Google's API Improvement Proposals](https://google.aip.dev/) (AIP) conventions. ## Base URL Your deployment's API base URL is: ``` {{ site.api_url }} ``` ## Authentication API requests are authenticated with [API keys](../account-management/api_keys.txt) using HTTP Basic auth. When you create a key, the UI provides a username and password you can use directly. ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues" \ -u "$API_KEY_USERNAME:$API_KEY_PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` API keys come in two access levels: | Level | Description | |:------|:------------| | **Read-only** | List and get resources, plus invoke triggers | | **Read-write** | All read-only access, plus create, update, and delete resources | ## Calling convention All API methods use HTTP `POST` with a JSON request body. The URL pattern is: ``` POST /{package}.{Service}/{Method} ``` Every request must include the header `Content-Type: application/json`. Requests accept both `snake_case` and `camelCase` field names. Responses always use `camelCase`. ## Resource names Resources are identified by a `name` field following the pattern `{collection}/{id}`. For example: - `known-issues/ki-auth-timeout` - `agents/my-agent` - `agents/my-agent/sessions/s-123` Nested resources include their parent's name as a prefix. ## Standard methods Most resources support some or all of these standard methods: | Method | Description | Key request fields | |:-------|:------------|:-------------------| | **Create** | Create a new resource | `{resource_id}`, `{resource}` object | | **Get** | Retrieve a single resource | `name` | | **List** | List resources with pagination | `page_size`, `page_token`, `filter`, `order_by` | | **Update** | Modify an existing resource | `{resource}` object with `name` set, `update_mask` | | **Delete** | Soft-delete a resource | `name` | ## Pagination List methods return results in pages. **Request fields** | Field | Description | |:------|:------------| | `page_size` | Maximum number of results per page (server may return fewer) | | `page_token` | Token from a previous `next_page_token` to fetch the next page | **Response fields** | Field | Description | |:------|:------------| | `next_page_token` | Token to pass as `page_token` in the next request. Empty when there are no more results. | ```bash # First page curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 10}' # Next page (using next_page_token from previous response) curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 10, "page_token": "..."}' ``` ## Filtering List methods accept a `filter` parameter for filtering results. The syntax is based on [AIP-160](https://google.aip.dev/160). ### Operators | Operator | Description | Example | |:---------|:------------|:--------| | `=` | Equals | `status = "KNOWN_ISSUE_STATUS_ACTIVE"` | | `!=` | Not equals | `status != "KNOWN_ISSUE_STATUS_RESOLVED"` | | `<` | Less than | `create_time < "2024-06-01T00:00:00Z"` | | `>` | Greater than | `create_time > "2024-01-01T00:00:00Z"` | | `<=` | Less than or equal | `create_time <= "2024-06-30T23:59:59Z"` | | `>=` | Greater than or equal | `create_time >= "2024-01-01T00:00:00Z"` | | `:` | Has / contains (wildcard) | `display_name : "*payments*"` | ### Combining filters Use `AND`, `OR`, and `NOT` to combine expressions: ```json {"filter": "status = \"KNOWN_ISSUE_STATUS_ACTIVE\" AND create_time > \"2024-01-01T00:00:00Z\""} ``` ### Field access Use dot-delimited paths to access nested fields and map keys: - `labels.environment = "production"` -- map value access - `origin.repository = "acme-corp/backend"` -- nested message field See each resource page for the filterable fields specific to that resource. ## Ordering List methods accept an `order_by` parameter to control sort order: ```json {"order_by": "create_time desc"} ``` Use `asc` (default) or `desc` after the field name. Dot-delimited paths work for nested fields (e.g. `origin.pr_number desc`). ## Partial updates Update methods accept an `update_mask` field (a [FieldMask](https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask)) to specify which fields to modify. Only the listed fields are changed; others are left untouched. The value is a comma-separated list of field paths. Dot-delimited paths address nested fields (e.g. `configuration.cron.schedule`). ```json { "known_issue": { "name": "known-issues/ki-auth-timeout", "status": "KNOWN_ISSUE_STATUS_RESOLVED" }, "update_mask": "status" } ``` If `update_mask` is omitted, all mutable fields in the request are updated. For repeated fields and map fields, the provided value replaces the existing value entirely -- there is no element-level merging. ## Soft delete Delete methods perform a soft delete by default. Soft-deleted resources: - Have a non-null `delete_time` timestamp - Are excluded from List results unless `show_deleted` is set to `true` - Can still be retrieved with Get by name ```json {"show_deleted": true} ``` ## Field behaviors Fields in the [resource type tables](types/) are annotated with behaviors: | Behavior | Meaning | |:---------|:--------| | **OUTPUT_ONLY** | Set by the server. Ignored if included in create/update requests. | | **REQUIRED** | Must be provided in create requests. | | *No annotation* | Optional. Can be set on create and modified with update. | ## Timestamps All timestamps are in [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format with UTC timezone: ``` "2024-06-15T14:30:00Z" ``` ## Error responses Errors are returned as JSON with an HTTP status code and a `code` string: ```json { "code": "not_found", "message": "known-issues/does-not-exist not found" } ``` | HTTP Status | Code | Description | |:------------|:-----|:------------| | 400 | `invalid_argument` | The request is malformed or a required field is missing | | 401 | `unauthenticated` | Missing or invalid credentials | | 403 | `permission_denied` | The API key doesn't have access to this method | | 404 | `not_found` | The requested resource doesn't exist | | 409 | `already_exists` | A resource with that ID already exists | | 500 | `internal` | Internal server error | ## Resources ### Read-write These resources support full CRUD operations with a read-write API key: - [Known Issues](known-issues.txt) — problems your team is tracking - [Customers](customers.txt) — customer definitions for scoping investigations - [Investigations](investigations.txt) — ad-hoc data investigations - [Notes](notes.txt) — free-form notes attached to resources - [Runbooks](runbooks.txt) — operational runbooks for agents - [Triggers](triggers.txt) — webhook triggers for agent invocation - [Agents](agents.txt) — autonomous agents, sessions, and message read/write - [Deployments](deployments.txt) — software deployment tracking - [Tags](tags.txt) — organize and filter agents with custom tags ### Read-only These resources are managed by the system and available for reading: - [Connections](connections.txt) — configured integrations and their sub-services - [Issues](issues.txt) — system-detected issues and notification policies - [Monitoring Plans](monitoring-plans.txt) — agent monitoring configurations and runs ### Reference - [Types](types/) — all resource types, enums, and shared types ## Agents Agents are automated workflows that monitor your systems and take action on your behalf. Each agent can have multiple sessions, which represent individual execution runs with their own message history and lifecycle. **Service**: `firetiger.nxagent.v2.AgentService` **Resource name patterns**: `agents/{agent_id}` and `agents/{agent_id}/sessions/{session_id}` **Access**: Read-write **Resource types**: [Agent](types/agent.txt), [Session](types/session.txt) ## Example flow Create an agent, send it a message (which auto-creates a session), then read the conversation back. **1. Create an agent** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/CreateAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "error-monitor", "agent": { "title": "Error Rate Monitor", "prompt": "You monitor production services for elevated error rates.", "connections": [ {"name": "connections/prod-postgres", "enabled_tools": ["TOOL_POSTGRES_QUERY"]}, {"name": "connections/prod-prometheus", "enabled_tools": ["TOOL_PROMQL_QUERY"]} ], "state": "AGENT_STATE_ON" } }' ``` **2. Send a message (auto-creates a session)** Writing to `parent` instead of `session` auto-creates a new session. The default write mode (`WRITE_MODE_CHECKPOINT`) triggers the agent to start processing. ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Write" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "parent": "agents/error-monitor", "messages": [ { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "text": {"text": "Check error rates for the payments service over the last hour."} } } ] }' ``` ```json {"session": "agents/error-monitor/sessions/ses-abc123", "sessionLength": "1"} ``` **3. Read messages back** Use the session name from the Write response to read the conversation. The agent's responses will appear as `assistant` activities. ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Read" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"session": "agents/error-monitor/sessions/ses-abc123", "session_offset": 0}' ``` ```json { "session": "agents/error-monitor/sessions/ses-abc123", "sessionOffset": "0", "sessionLength": "3", "messages": [ { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": {"text": {"text": "Check error rates for the payments service over the last hour."}} }, { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "assistant": { "text": {"text": "I'll query Prometheus for the payments service error rate."}, "toolCalls": [{"id": "tc-1", "name": "TOOL_PROMQL_QUERY", "arguments": "{\"query\": \"rate(http_requests_total{service=\\\"payments\\\",status=~\\\"5..\\\"}[1h])\"}"}] } }, { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "toolResults": [{"toolCallId": "tc-1", "content": "{\"status\":\"success\",\"data\":{\"result\":[{\"value\":\"0.02\"}]}}"}] } } ], "status": "STATUS_EXECUTING" } ``` **Write vs CreateSession**: Use [CreateSession](#createsession) when you need an empty session with metadata (like associated resources). Use [Write](#write) with `parent` to create a session and send a message in one call. ## Methods | Method | Description | |:-------|:------------| | [CreateAgent](#createagent) | Create a new agent | | [GetAgent](#getagent) | Retrieve an agent by name | | [ListAgents](#listagents) | List agents with filtering and pagination | | [UpdateAgent](#updateagent) | Update an existing agent | | [DeleteAgent](#deleteagent) | Soft-delete an agent | | [UndeleteAgent](#undeleteagent) | Restore a soft-deleted agent | | [CreateSession](#createsession) | Create a new session for an agent | | [GetSession](#getsession) | Retrieve a session by name | | [UpdateSession](#updatesession) | Update an existing session | | [DeleteSession](#deletesession) | Soft-delete a session | | [ListSessions](#listsessions) | List sessions for an agent or across all agents | | [DescribeSessions](#describesessions) | List sessions with runtime state (status, conclusion, last message) | | [Write](#write) | Send messages to a session | | [Read](#read) | Read messages from a session | | [GetArtifact](#getartifact) | Retrieve an artifact from a session | --- ## CreateAgent Create a new agent. ``` POST /firetiger.nxagent.v2.AgentService/CreateAgent ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `agent_id` | string | Yes | ID for the new agent (alphanumeric, hyphens, underscores; must start with a letter or digit) | | `agent` | [Agent](types/agent.txt) | No | Initial agent configuration (title, description, prompt, connections) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/CreateAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "my-monitor", "agent": { "title": "Production Error Monitor", "description": "Monitors production logs for error spikes and investigates root causes.", "prompt": "You are a production error monitor. Check for elevated error rates and investigate anomalies.", "connections": [ { "name": "connections/prod-postgres", "enabled_tools": ["TOOL_POSTGRES_QUERY"] } ], "state": "AGENT_STATE_ON" } }' ``` **Response** ```json { "agent": { "name": "agents/my-monitor", "title": "Production Error Monitor", "description": "Monitors production logs for error spikes and investigates root causes.", "prompt": "You are a production error monitor. Check for elevated error rates and investigate anomalies.", "connections": [ { "name": "connections/prod-postgres", "enabledTools": ["TOOL_POSTGRES_QUERY"] } ], "state": "AGENT_STATE_ON", "createdBy": "user_abc123", "createTime": "2024-06-15T10:00:00Z", "updateTime": "2024-06-15T10:00:00Z" } } ``` --- ## GetAgent Retrieve an agent by name. ``` POST /firetiger.nxagent.v2.AgentService/GetAgent ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the agent (`agents/{agent}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/GetAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "agents/my-monitor"}' ``` --- ## ListAgents List agents with optional filtering and pagination. ``` POST /firetiger.nxagent.v2.AgentService/ListAgents ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`). Supported fields: `create_time`, `update_time` | | `show_deleted` | boolean | No | Include soft-deleted agents | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/ListAgents" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 10}' ``` **Response** ```json { "agents": [ { "name": "agents/my-monitor", "title": "Production Error Monitor", "state": "AGENT_STATE_ON", "createTime": "2024-06-15T10:00:00Z", "updateTime": "2024-06-15T10:00:00Z" } ], "nextPageToken": "" } ``` --- ## UpdateAgent Update an existing agent. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.nxagent.v2.AgentService/UpdateAgent ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `agent` | [Agent](types/agent.txt) | Yes | The agent with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/UpdateAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "agent": { "name": "agents/my-monitor", "state": "AGENT_STATE_OFF" }, "update_mask": "state" }' ``` --- ## DeleteAgent Soft-delete an agent. The resource will still be accessible via GetAgent but excluded from ListAgents results unless `show_deleted` is set. ``` POST /firetiger.nxagent.v2.AgentService/DeleteAgent ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the agent to delete (`agents/{agent}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/DeleteAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "agents/my-monitor"}' ``` --- ## UndeleteAgent Restore a soft-deleted agent. ``` POST /firetiger.nxagent.v2.AgentService/UndeleteAgent ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the agent to restore (`agents/{agent}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/UndeleteAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "agents/my-monitor"}' ``` **Response** ```json { "agent": { "name": "agents/my-monitor", "title": "Production Error Monitor", "state": "AGENT_STATE_ON", "createTime": "2024-06-15T10:00:00Z", "updateTime": "2024-06-16T09:00:00Z" } } ``` --- ## CreateSession Create a new session for an agent, optionally with initial messages. ``` POST /firetiger.nxagent.v2.AgentService/CreateSession ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `parent` | string | Yes | Parent agent resource name (`agents/{agent}`) | | `session_id` | string | No | Session ID to use. If not provided, the server generates one. | | `initial_messages` | Any[] | No | Initial messages to write to the session upon creation | | `associated_resources` | string[] | No | Resource names to link to this session | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/CreateSession" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "parent": "agents/my-monitor", "session_id": "run-2024-06-15", "associated_resources": ["incidents/inc-001"] }' ``` **Response** ```json { "session": { "name": "agents/my-monitor/sessions/run-2024-06-15", "associatedResources": ["incidents/inc-001"], "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## GetSession Retrieve a session by name. ``` POST /firetiger.nxagent.v2.AgentService/GetSession ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the session (`agents/{agent}/sessions/{session}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/GetSession" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "agents/my-monitor/sessions/run-2024-06-15"}' ``` --- ## UpdateSession Update an existing session. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.nxagent.v2.AgentService/UpdateSession ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `session` | [Session](types/session.txt) | Yes | The session with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/UpdateSession" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "session": { "name": "agents/my-monitor/sessions/run-2024-06-15", "associated_resources": ["incidents/inc-001", "objectives/obj-002"] }, "update_mask": "associated_resources" }' ``` --- ## DeleteSession Soft-delete a session. The resource will still be accessible via GetSession but excluded from ListSessions results unless `show_deleted` is set. ``` POST /firetiger.nxagent.v2.AgentService/DeleteSession ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the session to delete (`agents/{agent}/sessions/{session}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/DeleteSession" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "agents/my-monitor/sessions/run-2024-06-15"}' ``` --- ## ListSessions List sessions for an agent (or across all agents) with optional filtering and pagination. Returns basic session metadata without runtime state. ``` POST /firetiger.nxagent.v2.AgentService/ListSessions ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `parent` | string | No | Parent agent resource name (`agents/{agent}`). If empty, lists sessions across all agents. | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `filter` | string | No | [Filter](index.txt#filtering) expression (e.g. `create_time >= '2024-01-01T00:00:00Z'`) | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`). Supported fields: `create_time`, `update_time` | | `show_deleted` | boolean | No | Include soft-deleted sessions | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/ListSessions" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"parent": "agents/my-monitor", "page_size": 25}' ``` **Response** ```json { "sessions": [ { "name": "agents/my-monitor/sessions/run-2024-06-15", "associatedResources": ["incidents/inc-001"], "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` --- ## DescribeSessions List sessions with runtime state from the execution engine, including status, session length, last message time, and conclusion. This is a richer alternative to [ListSessions](#listsessions). ``` POST /firetiger.nxagent.v2.AgentService/DescribeSessions ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `parent` | string | No | Parent agent resource name (`agents/{agent}`). If empty, describes sessions across all agents. | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`). Supported fields: `create_time`, `update_time` | | `show_deleted` | boolean | No | Include soft-deleted sessions | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/DescribeSessions" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"parent": "agents/my-monitor", "page_size": 10}' ``` **Response** Returns a list of [SessionDescription](types/session.txt#session-description) objects: ```json { "sessionDescriptions": [ { "session": { "name": "agents/my-monitor/sessions/run-2024-06-15", "associatedResources": ["incidents/inc-001"], "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" }, "status": "STATUS_WAITING", "sessionLength": 12, "lastMessage": "2024-06-15T15:45:00Z", "conclusion": { "done": { "message": "Investigation complete. Root cause identified as a memory leak in the auth service introduced in v2.3.", "issues": [ { "title": "Auth service memory leak", "description": "Memory usage grows linearly under load, causing OOM kills after ~4 hours of peak traffic." } ] } } } ], "nextPageToken": "" } ``` --- ## Write Send messages to an agent session. Messages are wrapped in [`google.protobuf.Any`](https://protobuf.dev/programming-guides/proto3/#any) and typically contain [Activity](types/activity.txt) protos. The `@type` field on each message tells the server how to decode it — for user messages, use `type.googleapis.com/firetiger.nxagent.v1.Activity`. A checkpoint write (the default) triggers the agent to process the new messages. You can target an existing session by name, or provide a `parent` agent to auto-create a new session. ``` POST /firetiger.nxagent.v2.AgentService/Write ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `session` | string | No | Resource name of the session to write to (`agents/{agent}/sessions/{session}`). Either `session` or `parent` must be set. | | `parent` | string | No | Parent agent resource name (`agents/{agent}`). If set (and `session` is empty), a new session is auto-created. | | `messages` | Any[] | Yes | Messages to write (must not be empty). Each message is a `google.protobuf.Any` with an `@type` field. | | `write_mode` | string | No | How to write: `WRITE_MODE_CHECKPOINT` (default, triggers agent), `WRITE_MODE_PROVISIONAL` (queued silently), or `WRITE_MODE_PROVISIONAL_OR_CHECKPOINT` (provisional if agent is running, checkpoint if idle). | **Example -- send a user message to a session** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Write" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "session": "agents/my-monitor/sessions/run-2024-06-15", "messages": [ { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "text": {"text": "Check the error rates for the payments service in the last hour."} } } ] }' ``` **Example -- auto-create a session and send a message** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Write" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "parent": "agents/my-monitor", "messages": [ { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "text": {"text": "Investigate elevated 500 errors on the checkout endpoint."} } } ] }' ``` **Response** ```json { "session": "agents/my-monitor/sessions/ses-abc123", "sessionLength": "1" } ``` --- ## Read Read messages from an agent session starting from a given offset. Returns the full conversation history as a list of `google.protobuf.Any` messages (typically [Activity](types/activity.txt) protos). ``` POST /firetiger.nxagent.v2.AgentService/Read ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `session` | string | Yes | Resource name of the session (`agents/{agent}/sessions/{session}`) | | `session_offset` | integer | No | Start reading from this message index (0-based). Defaults to 0. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Read" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "session": "agents/my-monitor/sessions/run-2024-06-15", "session_offset": 0 }' ``` **Response** ```json { "session": "agents/my-monitor/sessions/run-2024-06-15", "sessionOffset": "0", "sessionLength": "3", "messages": [ { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "text": {"text": "Check the error rates for the payments service."} }, "timestamp": "2024-06-15T14:30:00Z" }, { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "assistant": { "text": {"text": "I'll query the error rates now."}, "toolCalls": [ {"id": "tc-1", "name": "TOOL_PROMQL_QUERY", "arguments": "{\"query\": \"rate(http_requests_total{status=~\\\"5..\\\"}[1h])\"}"} ] }, "timestamp": "2024-06-15T14:30:05Z" }, { "@type": "type.googleapis.com/firetiger.nxagent.v1.Activity", "user": { "toolResults": [ {"toolCallId": "tc-1", "content": "{\"status\":\"success\",\"data\":{\"result\":[{\"value\":\"0.05\"}]}}"} ] }, "timestamp": "2024-06-15T14:30:10Z" } ], "status": "STATUS_WAITING" } ``` --- ## GetArtifact Retrieve an artifact from a session by its SHA-256 hash. ``` POST /firetiger.nxagent.v2.AgentService/GetArtifact ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `session` | string | Yes | Resource name of the session (`agents/{agent}/sessions/{session}`) | | `sha256` | string | Yes | SHA-256 hash of the artifact to retrieve | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/GetArtifact" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "session": "agents/my-monitor/sessions/run-2024-06-15", "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }' ``` ## Connections Connections are integrations with external tools and services. Each connection stores credentials and configuration for a specific external system (databases, SaaS platforms, cloud providers, etc.). **Service**: `firetiger.connections.v1.ConnectionsService` **Resource name pattern**: `connections/{connection_id}` **Access**: Read-only **Resource type**: [Connection](types/connection.txt) Connections are configured through the Firetiger UI. The API provides read-only access to list and inspect your configured connections. ## Example flow List your connections to see what is available, then fetch a specific one to inspect its full configuration. **1. List connections** ```bash curl -X POST "{{ site.api_url }}/firetiger.connections.v1.ConnectionsService/ListConnections" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "connections": [ { "name": "connections/prod-postgres", "displayName": "Production Postgres", "connectionType": "CONNECTION_TYPE_POSTGRES" }, { "name": "connections/staging-http", "displayName": "Staging API", "connectionType": "CONNECTION_TYPE_HTTP" } ] } ``` **2. Get a specific connection** Use the resource name from the list response to fetch full details, including resolved credentials and tool configurations. ```bash curl -X POST "{{ site.api_url }}/firetiger.connections.v1.ConnectionsService/GetConnection" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "connections/prod-postgres"}' ``` ```json { "connection": { "name": "connections/prod-postgres", "displayName": "Production Postgres", "description": "Primary production database", "connectionType": "CONNECTION_TYPE_POSTGRES", "connectionDetails": { "postgres": { "host": "db.example.com", "port": 5432, "database": "production", "username": "readonly", "password": "resolved-secret", "sslMode": "require" } }, "toolConfigurations": [ { "tool": "TOOL_POSTGRES_QUERY", "enabled": true } ] } } ``` ## Methods | Method | Description | |:-------|:------------| | [GetConnection](#getconnection) | Retrieve a connection by name | | [ListConnections](#listconnections) | List connections with filtering and pagination | | [ListConnectionTypes](#listconnectiontypes) | List all supported connection types | --- ## GetConnection Retrieve a connection by name. Returns full connection details including credentials fetched from the secrets provider. ``` POST /firetiger.connections.v1.ConnectionsService/GetConnection ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the connection (e.g. `connections/prod-postgres`) | | `override` | ConnectionDetailsOverride | No | Override to apply before resolution (e.g. restrict GitHub token scope) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.connections.v1.ConnectionsService/GetConnection" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "connections/prod-postgres"}' ``` --- ## ListConnections List connections with optional filtering and pagination. Connection details are not populated in list responses. ``` POST /firetiger.connections.v1.ConnectionsService/ListConnections ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression (e.g. `connection_type="postgres"`) | | `order_by` | string | No | Field to sort by | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted connections | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.connections.v1.ConnectionsService/ListConnections" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "connection_type=\"postgres\"", "page_size": 25}' ``` --- ## ListConnectionTypes List all supported connection types with their metadata and available tools. Returns only user-creatable types. ``` POST /firetiger.connections.v1.ConnectionsService/ListConnectionTypes ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Sort order | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.connections.v1.ConnectionsService/ListConnectionTypes" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` **Response** ```json { "types": [ { "type": "CONNECTION_TYPE_POSTGRES", "displayName": "PostgreSQL", "description": "Query PostgreSQL databases", "availableTools": ["TOOL_POSTGRES_QUERY"] } ] } ``` ## Customers Customers represent organizations or entities that use your product. Each customer is identified by an `external_id` drawn from your telemetry system (the value used in WHERE clauses to isolate that customer's requests). Firetiger hashes the external ID to produce a URL-safe resource name. **Service**: `firetiger.customers.v2.CustomersService` **Resource name pattern**: `customers/{customer_id}` **Access**: Read-write **Resource type**: [Customer](types/customer.txt) ## Example flow Create a customer, list customers to confirm it exists, then update a field. **1. Create a customer** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/CreateCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "acme-corp", "customer": { "external_id": "acme-corp", "display_name": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "runbook": "Check dashboard at https://internal.example.com/acme for SLO status before escalating." } }' ``` ```json { "customer": { "name": "customers/acme-corp", "externalId": "acme-corp", "id": "65a3089e664b", "displayName": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "runbook": "Check dashboard at https://internal.example.com/acme for SLO status before escalating.", "createTime": "2024-08-10T12:00:00Z", "updateTime": "2024-08-10T12:00:00Z" } } ``` **2. List customers** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/ListCustomers" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "customers": [ { "name": "customers/acme-corp", "externalId": "acme-corp", "id": "65a3089e664b", "displayName": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "createTime": "2024-08-10T12:00:00Z", "updateTime": "2024-08-10T12:00:00Z" } ], "nextPageToken": "" } ``` **3. Update the customer's description** Use `update_mask` to change only specific fields. Fields not in the mask are left untouched. ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/UpdateCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "customer": { "name": "customers/acme-corp", "description": "Enterprise SaaS customer, upgraded to Premium plan" }, "update_mask": "description" }' ``` ```json { "customer": { "name": "customers/acme-corp", "externalId": "acme-corp", "id": "65a3089e664b", "displayName": "Acme Corporation", "description": "Enterprise SaaS customer, upgraded to Premium plan", "runbook": "Check dashboard at https://internal.example.com/acme for SLO status before escalating.", "createTime": "2024-08-10T12:00:00Z", "updateTime": "2024-08-10T12:05:00Z" } } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateCustomer](#createcustomer) | Create a new customer | | [GetCustomer](#getcustomer) | Retrieve a customer by name | | [UpdateCustomer](#updatecustomer) | Update an existing customer | | [DeleteCustomer](#deletecustomer) | Soft-delete a customer | | [ListCustomers](#listcustomers) | List customers with filtering and pagination | --- ## CreateCustomer Create a new customer. ``` POST /firetiger.customers.v2.CustomersService/CreateCustomer ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `customer_id` | string | Yes | ID for the new customer (alphanumeric, hyphens, underscores; must start with a letter or digit) | | `customer` | [Customer](types/customer.txt) | Yes | The customer to create (must include `external_id`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/CreateCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "acme-corp", "customer": { "external_id": "acme-corp", "display_name": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "runbook": "Check dashboard at https://internal.example.com/acme for SLO status before escalating." } }' ``` **Response** ```json { "customer": { "name": "customers/acme-corp", "externalId": "acme-corp", "id": "65a3089e664b", "displayName": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "runbook": "Check dashboard at https://internal.example.com/acme for SLO status before escalating.", "createTime": "2024-08-10T12:00:00Z", "updateTime": "2024-08-10T12:00:00Z" } } ``` --- ## GetCustomer Retrieve a customer by name. ``` POST /firetiger.customers.v2.CustomersService/GetCustomer ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the customer | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/GetCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "customers/acme-corp"}' ``` --- ## UpdateCustomer Update an existing customer. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.customers.v2.CustomersService/UpdateCustomer ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `customer` | [Customer](types/customer.txt) | Yes | The customer with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/UpdateCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "customer": { "name": "customers/acme-corp", "description": "Enterprise SaaS customer, upgraded to Premium plan" }, "update_mask": "description" }' ``` --- ## DeleteCustomer Soft-delete a customer. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. ``` POST /firetiger.customers.v2.CustomersService/DeleteCustomer ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the customer to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/DeleteCustomer" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "customers/acme-corp"}' ``` --- ## ListCustomers List customers with optional filtering and pagination. ``` POST /firetiger.customers.v2.CustomersService/ListCustomers ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted customers | **Filter examples** - `display_name : '*acme*'` -- substring match on display name - `external_id = 'acme-corp'` -- exact match on external ID - `create_time > '2024-01-01T00:00:00Z'` -- customers created after a date **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.customers.v2.CustomersService/ListCustomers" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "display_name : \"*Acme*\"", "page_size": 25}' ``` **Response** ```json { "customers": [ { "name": "customers/acme-corp", "externalId": "acme-corp", "id": "65a3089e664b", "displayName": "Acme Corporation", "description": "Enterprise SaaS customer on the Business plan", "createTime": "2024-08-10T12:00:00Z", "updateTime": "2024-08-10T12:00:00Z" } ], "nextPageToken": "" } ``` --- A v1 API (`firetiger.customers.v1.CustomersService`) is also available but deprecated. Use v2 for new integrations. ## Deployments Deployments track software release events across your infrastructure. Each deployment records which code was shipped, to which environment, and its progression through status changes. Deployment monitor evaluations represent automated agent sessions that watch a deployment for anomalies after it lands. ## DeploymentsService **Service**: `firetiger.deployments.v1.DeploymentsService` **Resource name pattern**: `deployments/{deployment_id}` **Access**: Read-write **Resource types**: [Deployment](types/deployment.txt), [Deployment Status Event](types/deployment.txt#deployment-status-event) ## Example flow Create a deployment to record a release event, then list recent deployments. **1. Create a deployment** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/CreateDeployment" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "deployment_id": "github-12345", "deployment": { "source": "DEPLOYMENT_SOURCE_GITHUB", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "description": "Deploy main to production" } }' ``` ```json { "deployment": { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_PENDING", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "description": "Deploy main to production", "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:00:00Z" } } ``` **2. List recent production deployments** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/ListDeployments" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "filter": "labels.environment = \"production\"", "order_by": "create_time desc", "page_size": 5 }' ``` ```json { "deployments": [ { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_SUCCESS", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:05:00Z" } ], "nextPageToken": "" } ``` **3. Get a specific deployment** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/GetDeployment" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "deployments/github-12345"}' ``` ```json { "deployment": { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_SUCCESS", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:05:00Z", "startTime": "2025-03-01T10:01:00Z", "completeTime": "2025-03-01T10:05:00Z", "externalId": "12345", "externalUrl": "https://github.com/acme-corp/backend/deployments/12345", "description": "Deploy main to production" } } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateDeployment](#createdeployment) | Create a new deployment | | [GetDeployment](#getdeployment) | Retrieve a deployment by name | | [ListDeployments](#listdeployments) | List deployments with filtering and pagination | | [ListDeploymentStatusEvents](#listdeploymentstatusevents) | List the status event changelog for a deployment | --- ## CreateDeployment Create a new deployment to record a release event. ``` POST /firetiger.deployments.v1.DeploymentsService/CreateDeployment ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `deployment_id` | string | Yes | ID for the new deployment (alphanumeric, hyphens, underscores) | | `deployment` | [Deployment](types/deployment.txt) | Yes | The deployment to create | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/CreateDeployment" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "deployment_id": "github-12345", "deployment": { "source": "DEPLOYMENT_SOURCE_GITHUB", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "description": "Deploy main to production" } }' ``` **Response** ```json { "deployment": { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_PENDING", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "description": "Deploy main to production", "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:00:00Z" } } ``` --- ## GetDeployment Retrieve a deployment by name. ``` POST /firetiger.deployments.v1.DeploymentsService/GetDeployment ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the deployment (`deployments/{id}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/GetDeployment" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "deployments/github-12345"}' ``` **Response** ```json { "deployment": { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_SUCCESS", "labels": { "repository": "acme-corp/backend", "environment": "production", "ref": "main", "sha": "abc123def456" }, "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:05:00Z", "startTime": "2025-03-01T10:01:00Z", "completeTime": "2025-03-01T10:05:00Z", "externalId": "12345", "externalUrl": "https://github.com/acme-corp/backend/deployments/12345", "description": "Deploy main to production" } } ``` --- ## ListDeployments List deployments with optional filtering and pagination. ``` POST /firetiger.deployments.v1.DeploymentsService/ListDeployments ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted deployments | **Filter examples** - `labels.environment = "production"` -- deployments to production - `labels.repository = "acme-corp/backend"` -- deployments from a specific repository - `status = "DEPLOYMENT_STATUS_SUCCESS"` -- successful deployments - `create_time >= "2025-01-01T00:00:00Z"` -- deployments after a given date **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/ListDeployments" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "filter": "labels.environment = \"production\"", "order_by": "create_time desc", "page_size": 10 }' ``` **Response** ```json { "deployments": [ { "name": "deployments/github-12345", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_SUCCESS", "labels": { "repository": "acme-corp/backend", "environment": "production" }, "createTime": "2025-03-01T10:00:00Z", "updateTime": "2025-03-01T10:05:00Z" } ], "nextPageToken": "" } ``` --- ## ListDeploymentStatusEvents List the status event changelog for a deployment, showing how its status changed over time. ``` POST /firetiger.deployments.v1.DeploymentsService/ListDeploymentStatusEvents ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `parent` | string | Yes | Parent deployment resource name (`deployments/{id}`) | | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `event_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deployments.v1.DeploymentsService/ListDeploymentStatusEvents" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"parent": "deployments/github-12345", "page_size": 25}' ``` **Response** ```json { "statusEvents": [ { "name": "deployments/github-12345/status-events/evt-001", "deployment": "deployments/github-12345", "status": "DEPLOYMENT_STATUS_IN_PROGRESS", "description": "Deployment started", "eventTime": "2025-03-01T10:01:00Z", "createTime": "2025-03-01T10:01:00Z" }, { "name": "deployments/github-12345/status-events/evt-002", "deployment": "deployments/github-12345", "status": "DEPLOYMENT_STATUS_SUCCESS", "description": "Deployment completed successfully", "eventTime": "2025-03-01T10:05:00Z", "createTime": "2025-03-01T10:05:00Z" } ], "nextPageToken": "" } ``` --- ## DeploymentMonitorEvaluationService **Service**: `firetiger.deploy_monitor.v1.DeploymentMonitorEvaluationService` **Resource name pattern**: `deployment-monitor-evaluations/{evaluation_id}` **Access**: Read-write **Resource type**: [Deployment Monitor Evaluation](types/deployment.txt#deployment-monitor-evaluation) Deployment monitor evaluations represent automated agent sessions that watch a deployment for anomalies. When a deployment lands, the deploy-monitor agent starts a monitoring session, observes system behavior over a window of time, and produces a summary with an overall outcome. ## Methods | Method | Description | |:-------|:------------| | [GetDeploymentMonitorEvaluation](#getdeploymentmonitorevaluation) | Retrieve a deployment monitor evaluation by name | | [ListDeploymentMonitorEvaluations](#listdeploymentmonitorevaluations) | List evaluations with filtering and pagination | --- ## GetDeploymentMonitorEvaluation Retrieve a deployment monitor evaluation by name. ``` POST /firetiger.deploy_monitor.v1.DeploymentMonitorEvaluationService/GetDeploymentMonitorEvaluation ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the evaluation (`deployment-monitor-evaluations/{id}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deploy_monitor.v1.DeploymentMonitorEvaluationService/GetDeploymentMonitorEvaluation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "deployment-monitor-evaluations/eval-abc123"}' ``` **Response** ```json { "evaluation": { "name": "deployment-monitor-evaluations/eval-abc123", "createTime": "2025-03-01T10:05:00Z", "updateTime": "2025-03-01T10:35:00Z", "sessionName": "agents/deploy-monitor/sessions/sess-xyz789", "status": "DEPLOYMENT_MONITOR_EVALUATION_STATUS_COMPLETED", "githubRunId": "9876543210", "environment": "production", "repository": "acme-corp/backend", "headSha": "abc123def456", "baseSha": "789012ghi345", "prNumber": 42, "deploymentTime": "2025-03-01T10:00:00Z", "summary": "Deployment completed with no anomalies detected. All key metrics remained within expected ranges during the 30-minute monitoring window.", "overallStatus": "successful" } } ``` --- ## ListDeploymentMonitorEvaluations List deployment monitor evaluations with optional filtering and pagination. ``` POST /firetiger.deploy_monitor.v1.DeploymentMonitorEvaluationService/ListDeploymentMonitorEvaluations ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (default: `create_time desc`) | | `show_deleted` | boolean | No | Include soft-deleted evaluations | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.deploy_monitor.v1.DeploymentMonitorEvaluationService/ListDeploymentMonitorEvaluations" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "filter": "environment = \"production\"", "order_by": "create_time desc", "page_size": 10 }' ``` **Response** ```json { "evaluations": [ { "name": "deployment-monitor-evaluations/eval-abc123", "createTime": "2025-03-01T10:05:00Z", "updateTime": "2025-03-01T10:35:00Z", "status": "DEPLOYMENT_MONITOR_EVALUATION_STATUS_COMPLETED", "environment": "production", "repository": "acme-corp/backend", "headSha": "abc123def456", "overallStatus": "successful" } ], "nextPageToken": "" } ``` ## Investigations Investigations are agent-driven sessions that analyze and diagnose issues in your system. Each investigation tracks metadata like a display name, description, and execution status. **Service**: `firetiger.investigations.v1.InvestigationService` **Resource name pattern**: `investigations/{investigation_id}` **Access**: Read-write (no delete) **Resource type**: [Investigation](types/investigation.txt) ## Example flow Create an investigation to kick off an agent session, then poll for its status. **1. Create an investigation** The `description` becomes the agent's initial prompt, so describe the problem you want investigated. ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/CreateInvestigation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "investigation": { "display_name": "Elevated error rate in payments service", "description": "The payments service started returning 500s at 14:00 UTC. Investigate the root cause and affected scope." } }' ``` ```json { "investigation": { "name": "investigations/inv_abc123", "displayName": "Elevated error rate in payments service", "description": "The payments service started returning 500s at 14:00 UTC. Investigate the root cause and affected scope.", "status": "INVESTIGATION_STATUS_EXECUTING", "createdBy": "user_2xK9mBqHn1pL4vR7wT3eYjZ8aFd", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` **2. Check investigation status** Poll the investigation to see whether the agent has finished its analysis. ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/GetInvestigation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "investigations/inv_abc123"}' ``` ```json { "investigation": { "name": "investigations/inv_abc123", "displayName": "Elevated error rate in payments service", "description": "The payments service started returning 500s at 14:00 UTC. Investigate the root cause and affected scope.", "status": "INVESTIGATION_STATUS_WAITING", "createdBy": "user_2xK9mBqHn1pL4vR7wT3eYjZ8aFd", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:35:12Z" } } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateInvestigation](#createinvestigation) | Create a new investigation | | [GetInvestigation](#getinvestigation) | Retrieve an investigation by name | | [ListInvestigations](#listinvestigations) | List investigations with filtering and pagination | | [UpdateInvestigation](#updateinvestigation) | Update an existing investigation | --- ## CreateInvestigation Create a new investigation. The server auto-generates the investigation ID and starts an agent session. The `description` field becomes the agent's initial prompt, so it should describe the problem you want the agent to investigate. You can optionally seed the session with additional context via `initial_activities`. ``` POST /firetiger.investigations.v1.InvestigationService/CreateInvestigation ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `investigation` | [Investigation](types/investigation.txt) | Yes | The investigation to create. Only `display_name` and `description` are accepted; other fields are set by the server. | | `initial_activities` | [Activity](types/activity.txt)[] | No | Initial activities to seed the investigation session with. Use these to provide additional context beyond the description, such as log snippets, metric data, or prior analysis from other sessions. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/CreateInvestigation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "investigation": { "display_name": "Elevated error rate in payments service", "description": "The payments service started returning 500s at 14:00 UTC. Investigate the root cause and affected scope." } }' ``` **Response** ```json { "investigation": { "name": "investigations/inv_abc123", "displayName": "Elevated error rate in payments service", "description": "The payments service started returning 500s at 14:00 UTC. Investigate the root cause and affected scope.", "status": "INVESTIGATION_STATUS_EXECUTING", "createdBy": "user_2xK9mBqHn1pL4vR7wT3eYjZ8aFd", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## GetInvestigation Retrieve an investigation by name. ``` POST /firetiger.investigations.v1.InvestigationService/GetInvestigation ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the investigation (`investigations/{id}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/GetInvestigation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "investigations/inv_abc123"}' ``` --- ## ListInvestigations List investigations with optional filtering and pagination. ``` POST /firetiger.investigations.v1.InvestigationService/ListInvestigations ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression (e.g. `status = INVESTIGATION_STATUS_EXECUTING`) | | `order_by` | string | No | Field to sort by. Supported: `create_time`, `update_time`, `display_name`. Append ` desc` or ` asc` for direction. Default: `create_time desc`. | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted investigations | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/ListInvestigations" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "status = \"INVESTIGATION_STATUS_EXECUTING\"", "page_size": 25}' ``` **Response** ```json { "investigations": [ { "name": "investigations/inv_abc123", "displayName": "Elevated error rate in payments service", "status": "INVESTIGATION_STATUS_EXECUTING", "createdBy": "user_2xK9mBqHn1pL4vR7wT3eYjZ8aFd", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` --- ## UpdateInvestigation Update an existing investigation's metadata. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.investigations.v1.InvestigationService/UpdateInvestigation ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `investigation` | [Investigation](types/investigation.txt) | Yes | The investigation with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. Supported: `display_name`, `description`, `status`. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.investigations.v1.InvestigationService/UpdateInvestigation" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "investigation": { "name": "investigations/inv_abc123", "display_name": "Payments 500s - resolved: bad deploy" }, "update_mask": "display_name" }' ``` ## Issues Issues are problems detected automatically by Firetiger's monitoring agents. Each issue represents a distinct problem observed in your system, linked to the agent session that discovered it. Issues are managed by the system and available as read-only resources. Issues are the raw findings from agents. To group related issues and track them over time, use [Known Issues](known-issues.txt). This page also covers the issue notification policy, which controls how and where Firetiger sends alerts when new issues are detected. **Services**: `firetiger.issues.v1.IssuesService`, `firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService` **Resource name patterns**: `issues/{issue_id}` and `issue-notification-policies/{issue_notification_policy_id}` **Access**: Issues are read-only. The notification policy is read-write. **Resource types**: [Issue](types/issue.txt), [Issue Notification Policy](types/issue.txt#issue-notification-policy) ## Example flow List recent issues with a filter, get a specific one, then update the notification policy to route alerts to a new channel. **1. List issues** ```bash curl -X POST "{{ site.api_url }}/firetiger.issues.v1.IssuesService/ListIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 10}' ``` ```json { "issues": [ { "name": "issues/iss-db-connection-pool", "displayName": "Database connection pool exhaustion", "description": "The primary database connection pool is consistently hitting its max limit during peak hours.", "session": "agents/monitor/sessions/s-abc123", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ] } ``` **2. Get a specific issue** ```bash curl -X POST "{{ site.api_url }}/firetiger.issues.v1.IssuesService/GetIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "issues/iss-db-connection-pool"}' ``` ```json { "issue": { "name": "issues/iss-db-connection-pool", "displayName": "Database connection pool exhaustion", "description": "The primary database connection pool is consistently hitting its max limit during peak hours, causing request queuing and timeouts for downstream services.", "session": "agents/monitor/sessions/s-abc123", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` **3. Update the notification policy** ```bash curl -X POST "{{ site.api_url }}/firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService/UpdateIssueNotificationPolicy" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "issue_notification_policy": { "connections": ["connections/slack-oncall", "connections/pagerduty-prod"], "prompt": "Send critical issues to #oncall-alerts in Slack and create a PagerDuty incident." }, "update_mask": "connections,prompt" }' ``` ```json { "issueNotificationPolicy": { "name": "issue-notification-policies/default", "description": "Route critical issues to the on-call Slack channel and PagerDuty", "connections": [ "connections/slack-oncall", "connections/pagerduty-prod" ], "prompt": "Send critical issues to #oncall-alerts in Slack and create a PagerDuty incident.", "state": "ISSUE_NOTIFICATION_POLICY_STATE_ACTIVE", "createTime": "2024-06-10T09:00:00Z", "updateTime": "2024-06-16T10:15:00Z" } } ``` ## Methods | Method | Service | Description | |:-------|:--------|:------------| | [GetIssue](#getissue) | IssuesService | Retrieve an issue by name | | [ListIssues](#listissues) | IssuesService | List issues with filtering and pagination | | [GetIssueNotificationPolicy](#getissuenotificationpolicy) | IssueNotificationPolicyService | Retrieve the current notification policy | | [UpdateIssueNotificationPolicy](#updateissuenotificationpolicy) | IssueNotificationPolicyService | Update the notification policy | --- ## GetIssue Retrieve an issue by name. ``` POST /firetiger.issues.v1.IssuesService/GetIssue ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the issue (`issues/{id}`) | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.issues.v1.IssuesService/GetIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "issues/iss-db-connection-pool"}' ``` **Response** ```json { "issue": { "name": "issues/iss-db-connection-pool", "displayName": "Database connection pool exhaustion", "description": "The primary database connection pool is consistently hitting its max limit during peak hours, causing request queuing and timeouts for downstream services.", "session": "agents/monitor/sessions/s-abc123", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## ListIssues List issues with optional filtering and pagination. ``` POST /firetiger.issues.v1.IssuesService/ListIssues ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted issues | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.issues.v1.IssuesService/ListIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 25}' ``` **Response** ```json { "issues": [ { "name": "issues/iss-db-connection-pool", "displayName": "Database connection pool exhaustion", "description": "The primary database connection pool is consistently hitting its max limit during peak hours, causing request queuing and timeouts for downstream services.", "session": "agents/monitor/sessions/s-abc123", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` --- ## GetIssueNotificationPolicy Retrieve the current issue notification policy. The notification policy is a singleton resource that controls how Firetiger routes alerts when issues are detected. It defines which connections (e.g. Slack, PagerDuty) receive notifications and includes a prompt that guides the notification agent's behavior. ``` POST /firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService/GetIssueNotificationPolicy ``` **Request body** This method takes no parameters. Send an empty JSON object. **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService/GetIssueNotificationPolicy" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` **Response** ```json { "issueNotificationPolicy": { "name": "issue-notification-policies/default", "description": "Route critical issues to the on-call Slack channel and PagerDuty", "connections": [ "connections/slack-oncall", "connections/pagerduty-prod" ], "prompt": "Send critical issues to #oncall-alerts in Slack and create a PagerDuty incident. For non-critical issues, post to #issues in Slack only.", "state": "ISSUE_NOTIFICATION_POLICY_STATE_ACTIVE", "createTime": "2024-06-10T09:00:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## UpdateIssueNotificationPolicy Update the issue notification policy. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService/UpdateIssueNotificationPolicy ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `issue_notification_policy` | [IssueNotificationPolicy](types/issue.txt#issue-notification-policy) | Yes | The policy with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.issuenotificationpolicy.v1.IssueNotificationPolicyService/UpdateIssueNotificationPolicy" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "issue_notification_policy": { "name": "issue-notification-policies/default", "connections": [ "connections/slack-oncall", "connections/pagerduty-prod", "connections/email-eng-leads" ], "prompt": "Send critical issues to #oncall-alerts in Slack and create a PagerDuty incident. For non-critical issues, post to #issues in Slack and email engineering leads." }, "update_mask": "connections,prompt" }' ``` **Response** ```json { "issueNotificationPolicy": { "name": "issue-notification-policies/default", "description": "Route critical issues to the on-call Slack channel and PagerDuty", "connections": [ "connections/slack-oncall", "connections/pagerduty-prod", "connections/email-eng-leads" ], "prompt": "Send critical issues to #oncall-alerts in Slack and create a PagerDuty incident. For non-critical issues, post to #issues in Slack and email engineering leads.", "state": "ISSUE_NOTIFICATION_POLICY_STATE_ACTIVE", "createTime": "2024-06-10T09:00:00Z", "updateTime": "2024-06-16T10:15:00Z" } } ``` ## Known Issues Known issues are problems your team is actively tracking. They can be linked to objectives, and Firetiger's agents use them to contextualize new findings against previously seen problems. While [Issues](issues.txt) are raw findings submitted by agents, known issues let you curate and group those findings into tracked problems with their own lifecycle (active, resolved, etc.). **Service**: `firetiger.knownissues.v1.KnownIssuesService` **Resource name pattern**: `known-issues/{known_issue_id}` **Access**: Read-write **Resource type**: [Known Issue](types/known-issue.txt) ## Example flow Create a known issue to track a recurring problem, list active issues to check on it, then mark it resolved once the fix is deployed. **1. Create a known issue** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/CreateKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "known_issue_id": "ki-db-connection-pool", "known_issue": { "title": "Database connection pool exhaustion under load", "context": "First observed after migrating to the new connection pooler. Connections are not being released properly when queries time out.", "human_description": "Under sustained load, the database connection pool fills up and new queries start failing with connection timeout errors.", "status": "KNOWN_ISSUE_STATUS_ACTIVE" } }' ``` ```json { "knownIssue": { "name": "known-issues/ki-db-connection-pool", "title": "Database connection pool exhaustion under load", "context": "First observed after migrating to the new connection pooler. Connections are not being released properly when queries time out.", "humanDescription": "Under sustained load, the database connection pool fills up and new queries start failing with connection timeout errors.", "status": "KNOWN_ISSUE_STATUS_ACTIVE", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` **2. List active known issues** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "status = \"KNOWN_ISSUE_STATUS_ACTIVE\""}' ``` ```json { "knownIssues": [ { "name": "known-issues/ki-db-connection-pool", "title": "Database connection pool exhaustion under load", "status": "KNOWN_ISSUE_STATUS_ACTIVE", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` **3. Mark it resolved after deploying a fix** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/UpdateKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "known_issue": { "name": "known-issues/ki-db-connection-pool", "status": "KNOWN_ISSUE_STATUS_RESOLVED" }, "update_mask": "status" }' ``` ```json { "knownIssue": { "name": "known-issues/ki-db-connection-pool", "title": "Database connection pool exhaustion under load", "context": "First observed after migrating to the new connection pooler. Connections are not being released properly when queries time out.", "humanDescription": "Under sustained load, the database connection pool fills up and new queries start failing with connection timeout errors.", "status": "KNOWN_ISSUE_STATUS_RESOLVED", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T15:45:00Z" } } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateKnownIssue](#createknownissue) | Create a new known issue | | [GetKnownIssue](#getknownissue) | Retrieve a known issue by name | | [UpdateKnownIssue](#updateknownissue) | Update an existing known issue | | [DeleteKnownIssue](#deleteknownissue) | Soft-delete a known issue | | [ListKnownIssues](#listknownissues) | List known issues with filtering and pagination | --- ## CreateKnownIssue Create a new known issue. ``` POST /firetiger.knownissues.v1.KnownIssuesService/CreateKnownIssue ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `known_issue_id` | string | Yes | ID for the new known issue (alphanumeric, hyphens, underscores) | | `known_issue` | [KnownIssue](types/known-issue.txt) | Yes | The known issue to create | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/CreateKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "known_issue_id": "ki-auth-timeout", "known_issue": { "title": "Auth service timeouts during peak hours", "context": "Started after the v2.3 deploy. Auth service pods are hitting memory limits.", "human_description": "The auth service times out intermittently during peak traffic, causing login failures for about 5% of users.", "status": "KNOWN_ISSUE_STATUS_ACTIVE" } }' ``` **Response** ```json { "knownIssue": { "name": "known-issues/ki-auth-timeout", "title": "Auth service timeouts during peak hours", "context": "Started after the v2.3 deploy. Auth service pods are hitting memory limits.", "humanDescription": "The auth service times out intermittently during peak traffic, causing login failures for about 5% of users.", "status": "KNOWN_ISSUE_STATUS_ACTIVE", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## GetKnownIssue Retrieve a known issue by name. ``` POST /firetiger.knownissues.v1.KnownIssuesService/GetKnownIssue ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the known issue | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/GetKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "known-issues/ki-auth-timeout"}' ``` --- ## UpdateKnownIssue Update an existing known issue. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.knownissues.v1.KnownIssuesService/UpdateKnownIssue ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `known_issue` | [KnownIssue](types/known-issue.txt) | Yes | The known issue with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/UpdateKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "known_issue": { "name": "known-issues/ki-auth-timeout", "status": "KNOWN_ISSUE_STATUS_RESOLVED" }, "update_mask": "status" }' ``` --- ## DeleteKnownIssue Soft-delete a known issue. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. ``` POST /firetiger.knownissues.v1.KnownIssuesService/DeleteKnownIssue ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the known issue to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/DeleteKnownIssue" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "known-issues/ki-auth-timeout"}' ``` --- ## ListKnownIssues List known issues with optional filtering and pagination. ``` POST /firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted known issues | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.knownissues.v1.KnownIssuesService/ListKnownIssues" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "status = \"KNOWN_ISSUE_STATUS_ACTIVE\"", "page_size": 25}' ``` **Response** ```json { "knownIssues": [ { "name": "known-issues/ki-auth-timeout", "title": "Auth service timeouts during peak hours", "status": "KNOWN_ISSUE_STATUS_ACTIVE", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` ## Monitoring Plans Monitoring plans track deployment risk for pull requests. When a PR is merged and deployed, Firetiger monitors the deployment for unintended effects based on a plan written by an agent during code review. This page covers two services: **MonitoringPlanService** for plan lifecycle and **MonitoringRunService** (legacy) for backward-compatible run access. **Services**: `firetiger.monitoring_plans.v1.MonitoringPlanService`, `firetiger.monitoring_plans.v1.MonitoringRunService` **Resource name patterns**: `monitoring-plans/{plan_id}` and `monitoring-plans/{plan_id}/runs/{run_id}` **Access**: Read-only **Resource types**: [Monitoring Plan](types/monitoring-plan.txt), [Monitoring Run](types/monitoring-plan.txt#monitoring-run) ## Example flow List recent monitoring plans, then fetch details for a specific one. **1. List monitoring plans** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringPlanService/ListMonitoringPlans" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 5, "order_by": "create_time desc"}' ``` ```json { "monitoringPlans": [ { "name": "monitoring-plans/plan-abc123", "origin": { "repository": "acme-corp/backend", "prNumber": 42, "prTitle": "Fix auth service timeout handling", "prAuthor": "engineer" }, "planSummary": "Fixes auth service timeout handling to prevent cascading failures during peak traffic.", "createTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` **2. Get plan details** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringPlanService/GetMonitoringPlan" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "monitoring-plans/plan-abc123"}' ``` ```json { "monitoringPlan": { "name": "monitoring-plans/plan-abc123", "origin": { "repository": "acme-corp/backend", "prNumber": 42, "prUrl": "https://github.com/acme-corp/backend/pull/42", "headSha": "a1b2c3d4e5f6", "prTitle": "Fix auth service timeout handling", "prAuthor": "engineer" }, "activation": { "mergeSha": "f6e5d4c3b2a1", "environments": ["production"] }, "planContent": "## Intended Effect\nFixes timeout handling in auth service...", "planSummary": "Fixes auth service timeout handling to prevent cascading failures during peak traffic.", "notificationChannel": "#deploy-alerts", "authorSession": "agents/plan-author/sessions/sess-xyz", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T15:00:00Z", "deployments": [ { "environment": "production", "deployment": "deployments/dep-789", "deployTime": "2024-06-15T16:00:00Z", "intendedEffectConfirmed": true, "outcome": "MONITORING_OUTCOME_NO_ISSUE", "completeTime": "2024-06-15T17:30:00Z" } ], "lastCheckTime": "2024-06-15T17:30:00Z" } } ``` ## Methods | Method | Service | Description | |:-------|:--------|:------------| | [GetMonitoringPlan](#getmonitoringplan) | MonitoringPlanService | Retrieve a monitoring plan by name | | [ListMonitoringPlans](#listmonitoringplans) | MonitoringPlanService | List monitoring plans with filtering and pagination | | [GetMonitoringRun](#getmonitoringrun) | MonitoringRunService | Retrieve a monitoring run by name | | [ListMonitoringRuns](#listmonitoringruns) | MonitoringRunService | List monitoring runs for a plan | --- ## GetMonitoringPlan Retrieve a monitoring plan by name. ``` POST /firetiger.monitoring_plans.v1.MonitoringPlanService/GetMonitoringPlan ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the monitoring plan | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringPlanService/GetMonitoringPlan" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "monitoring-plans/plan-abc123"}' ``` **Response** ```json { "monitoringPlan": { "name": "monitoring-plans/plan-abc123", "origin": { "repository": "acme-corp/backend", "prNumber": 42, "prUrl": "https://github.com/acme-corp/backend/pull/42", "headSha": "a1b2c3d4e5f6", "prTitle": "Fix auth service timeout handling", "prAuthor": "engineer" }, "activation": { "mergeSha": "f6e5d4c3b2a1", "environments": ["production"] }, "planContent": "## Intended Effect\nFixes timeout handling in auth service...", "planSummary": "Fixes auth service timeout handling to prevent cascading failures during peak traffic.", "notificationChannel": "#deploy-alerts", "authorSession": "agents/plan-author/sessions/sess-xyz", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T15:00:00Z", "deployments": [ { "environment": "production", "deployment": "deployments/dep-789", "deployTime": "2024-06-15T16:00:00Z", "intendedEffectConfirmed": true, "outcome": "MONITORING_OUTCOME_NO_ISSUE", "completeTime": "2024-06-15T17:30:00Z" } ], "lastCheckTime": "2024-06-15T17:30:00Z" } } ``` --- ## ListMonitoringPlans List monitoring plans with optional filtering and pagination. ``` POST /firetiger.monitoring_plans.v1.MonitoringPlanService/ListMonitoringPlans ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted monitoring plans | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringPlanService/ListMonitoringPlans" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 10, "order_by": "create_time desc"}' ``` **Response** ```json { "monitoringPlans": [ { "name": "monitoring-plans/plan-abc123", "origin": { "repository": "acme-corp/backend", "prNumber": 42, "prUrl": "https://github.com/acme-corp/backend/pull/42", "prTitle": "Fix auth service timeout handling", "prAuthor": "engineer" }, "planSummary": "Fixes auth service timeout handling to prevent cascading failures during peak traffic.", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T15:00:00Z" } ], "nextPageToken": "" } ``` --- ## GetMonitoringRun > MonitoringRunService is a legacy service. New monitoring state is stored directly on MonitoringPlan.deployments. The run endpoints are retained for backward compatibility. Retrieve a monitoring run by name. ``` POST /firetiger.monitoring_plans.v1.MonitoringRunService/GetMonitoringRun ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the monitoring run | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringRunService/GetMonitoringRun" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "monitoring-plans/plan-abc123/runs/run-prod-001"}' ``` **Response** ```json { "monitoringRun": { "name": "monitoring-plans/plan-abc123/runs/run-prod-001", "environment": "production", "deployment": "deployments/dep-789", "status": "MONITORING_RUN_STATUS_COMPLETED", "outcome": "MONITORING_RUN_OUTCOME_NO_ISSUE", "intendedEffectConfirmed": true, "activateTime": "2024-06-15T16:00:00Z", "completeTime": "2024-06-15T17:30:00Z", "lastCheckTime": "2024-06-15T17:30:00Z", "createTime": "2024-06-15T16:00:00Z", "updateTime": "2024-06-15T17:30:00Z" } } ``` --- ## ListMonitoringRuns > MonitoringRunService is a legacy service. New monitoring state is stored directly on MonitoringPlan.deployments. The run endpoints are retained for backward compatibility. List monitoring runs for a plan with optional filtering and pagination. ``` POST /firetiger.monitoring_plans.v1.MonitoringRunService/ListMonitoringRuns ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `parent` | string | Yes | Parent monitoring plan resource name | | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted monitoring runs | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.monitoring_plans.v1.MonitoringRunService/ListMonitoringRuns" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"parent": "monitoring-plans/plan-abc123", "page_size": 10}' ``` **Response** ```json { "monitoringRuns": [ { "name": "monitoring-plans/plan-abc123/runs/run-prod-001", "environment": "production", "deployment": "deployments/dep-789", "status": "MONITORING_RUN_STATUS_COMPLETED", "outcome": "MONITORING_RUN_OUTCOME_NO_ISSUE", "intendedEffectConfirmed": true, "activateTime": "2024-06-15T16:00:00Z", "completeTime": "2024-06-15T17:30:00Z", "createTime": "2024-06-15T16:00:00Z", "updateTime": "2024-06-15T17:30:00Z" } ], "nextPageToken": "" } ``` ## Notes Notes are free-form records for capturing observations, tool outputs, and context. Each note can optionally reference the tool that produced it, along with the arguments used. **Service**: `firetiger.notes.v1.NotesService` **Resource name pattern**: `notes/{note_id}` **Access**: Read-write **Resource type**: [Note](types/note.txt) ## Example flow Create a couple of notes to capture tool outputs, then list them. **1. Create a note from a health check tool** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/CreateNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "note_id": "deploy-check-2024-06-15", "note": { "display_name": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "tool_name": "health_check", "tool_args": {"environment": "production", "timeout_seconds": 30} } }' ``` ```json { "note": { "name": "notes/deploy-check-2024-06-15", "displayName": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "toolName": "health_check", "toolArgs": {"environment": "production", "timeoutSeconds": 30}, "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` **2. Create a second note from a query tool** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/CreateNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "note_id": "error-spike-analysis", "note": { "display_name": "Error spike analysis", "notes": "Spike in 5xx errors between 14:00-14:15 UTC traced to a bad config push. Rolled back at 14:12.", "tool_name": "log_query", "tool_args": {"query": "status >= 500", "time_range": "1h"} } }' ``` ```json { "note": { "name": "notes/error-spike-analysis", "displayName": "Error spike analysis", "notes": "Spike in 5xx errors between 14:00-14:15 UTC traced to a bad config push. Rolled back at 14:12.", "toolName": "log_query", "toolArgs": {"query": "status >= 500", "timeRange": "1h"}, "createTime": "2024-06-15T14:35:00Z", "updateTime": "2024-06-15T14:35:00Z" } } ``` **3. List notes filtered by tool** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/ListNotes" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "tool_name = \"health_check\"", "page_size": 25}' ``` ```json { "notes": [ { "name": "notes/deploy-check-2024-06-15", "displayName": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "toolName": "health_check", "toolArgs": {"environment": "production", "timeoutSeconds": 30}, "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateNote](#createnote) | Create a new note | | [GetNote](#getnote) | Retrieve a note by name | | [UpdateNote](#updatenote) | Update an existing note | | [DeleteNote](#deletenote) | Soft-delete a note | | [ListNotes](#listnotes) | List notes with filtering and pagination | --- ## CreateNote Create a new note. ``` POST /firetiger.notes.v1.NotesService/CreateNote ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `note_id` | string | Yes | ID for the new note (alphanumeric, hyphens, underscores) | | `note` | [Note](types/note.txt) | Yes | The note to create | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/CreateNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "note_id": "deploy-check-2024-06-15", "note": { "display_name": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "tool_name": "health_check", "tool_args": {"environment": "production", "timeout_seconds": 30} } }' ``` **Response** ```json { "note": { "name": "notes/deploy-check-2024-06-15", "displayName": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "toolName": "health_check", "toolArgs": {"environment": "production", "timeoutSeconds": 30}, "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## GetNote Retrieve a note by name. ``` POST /firetiger.notes.v1.NotesService/GetNote ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the note | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/GetNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "notes/deploy-check-2024-06-15"}' ``` --- ## UpdateNote Update an existing note. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.notes.v1.NotesService/UpdateNote ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `note` | [Note](types/note.txt) | Yes | The note with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/UpdateNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "note": { "name": "notes/deploy-check-2024-06-15", "notes": "All endpoints returning 200. P99 latency stable at 120ms. Confirmed no error rate increase after 1 hour." }, "update_mask": "notes" }' ``` --- ## DeleteNote Soft-delete a note. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. ``` POST /firetiger.notes.v1.NotesService/DeleteNote ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the note to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/DeleteNote" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "notes/deploy-check-2024-06-15"}' ``` --- ## ListNotes List notes with optional filtering and pagination. ``` POST /firetiger.notes.v1.NotesService/ListNotes ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted notes | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.notes.v1.NotesService/ListNotes" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "tool_name = \"health_check\"", "page_size": 25}' ``` **Response** ```json { "notes": [ { "name": "notes/deploy-check-2024-06-15", "displayName": "Post-deploy health check", "notes": "All endpoints returning 200. P99 latency stable at 120ms.", "description": "Routine check after v2.4 rollout", "toolName": "health_check", "toolArgs": {"environment": "production", "timeoutSeconds": 30}, "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` ## Tags Tags let you organize and filter agents. There are two types of tags: - **User tags** — Created and managed by users with custom colors - **System tags** — Created by Firetiger (prefixed with `firetiger:`), always displayed in grey, read-only **Service**: `firetiger.tags.v1.TagsService` **Resource name pattern**: `tags/{tag_id}` **Access**: Read-write (user tags only; system tags are read-only) **Resource type**: [Tag](types/tag.txt) ## Example flow Create a tag, assign it to an agent, then list tags. **1. Create a tag** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/CreateTag" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "tag_id": "production", "tag": { "display_name": "Production", "description": "Agents monitoring production systems", "color": "#5E6AD2" } }' ``` ```json { "tag": { "name": "tags/production", "displayName": "Production", "description": "Agents monitoring production systems", "color": "#5E6AD2", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` **2. Assign tag to an agent** ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/UpdateAgent" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "agent": { "name": "agents/my-agent", "tags": ["tags/production"] }, "update_mask": "tags" }' ``` **3. List all tags** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/ListTags" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "tags": [ { "name": "tags/production", "displayName": "Production", "description": "Agents monitoring production systems", "color": "#5E6AD2", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ] } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateTag](#createtag) | Create a new tag | | [GetTag](#gettag) | Retrieve a tag by name | | [UpdateTag](#updatetag) | Update an existing tag | | [DeleteTag](#deletetag) | Soft-delete a tag | | [ListTags](#listtags) | List tags with filtering and pagination | --- ## CreateTag Create a new user tag. Cannot create system tags (those with `firetiger:` prefix). ``` POST /firetiger.tags.v1.TagsService/CreateTag ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `tag_id` | string | Yes | ID for the new tag (alphanumeric, hyphens, underscores, colons) | | `tag` | [Tag](types/tag.txt) | Yes | The tag to create | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/CreateTag" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "tag_id": "deploy-monitoring", "tag": { "display_name": "Deployment Monitoring", "color": "#10B981" } }' ``` **Response** ```json { "tag": { "name": "tags/deploy-monitoring", "displayName": "Deployment Monitoring", "color": "#10B981", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } } ``` --- ## GetTag Retrieve a tag by name. ``` POST /firetiger.tags.v1.TagsService/GetTag ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the tag | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/GetTag" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "tags/production"}' ``` --- ## UpdateTag Update an existing tag. Use `update_mask` to specify which fields to modify. Cannot update system tags. ``` POST /firetiger.tags.v1.TagsService/UpdateTag ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `tag` | [Tag](types/tag.txt) | Yes | The tag with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/UpdateTag" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "tag": { "name": "tags/production", "color": "#EF4444" }, "update_mask": "color" }' ``` --- ## DeleteTag Soft-delete a tag. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. Cannot delete system tags. ``` POST /firetiger.tags.v1.TagsService/DeleteTag ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the tag to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/DeleteTag" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "tags/production"}' ``` --- ## ListTags List tags with optional filtering and pagination. ``` POST /firetiger.tags.v1.TagsService/ListTags ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression (e.g., `system = true`) | | `order_by` | string | No | Field to sort by (e.g., `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted tags | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.tags.v1.TagsService/ListTags" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "system = false", "page_size": 25}' ``` **Response** ```json { "tags": [ { "name": "tags/production", "displayName": "Production", "color": "#5E6AD2", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ], "nextPageToken": "" } ``` ## Runbooks Runbooks are structured operating procedures that Firetiger agents follow when investigating or resolving issues. Each runbook contains instructional text and a set of connections with specific tools that the agent is allowed to use while executing the runbook. **Service**: `firetiger.runbooks.v1.RunbooksService` **Resource name pattern**: `runbooks/{runbook_id}` **Access**: Read-write **Resource type**: [Runbook](types/runbook.txt) ## Example flow Create a runbook that pairs connections with specific tools, then list all runbooks. **1. Create a runbook with connections and tools** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/CreateRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "runbook_id": "high-error-rate-triage", "runbook": { "display_name": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "text": "1. Query the database for recent deployments.\n2. Check HTTP error rates via Prometheus.\n3. If a recent deploy correlates, escalate to the owning team.", "connections": [ { "name": "connections/prod-postgres", "enabled_tools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabled_tools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ] } }' ``` ```json { "runbook": { "name": "runbooks/high-error-rate-triage", "displayName": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "text": "1. Query the database for recent deployments.\n2. Check HTTP error rates via Prometheus.\n3. If a recent deploy correlates, escalate to the owning team.", "connections": [ { "name": "connections/prod-postgres", "enabledTools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabledTools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ], "createTime": "2024-08-10T09:00:00Z", "updateTime": "2024-08-10T09:00:00Z" } } ``` **2. Create a second runbook** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/CreateRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "runbook_id": "deployment-rollback", "runbook": { "display_name": "Deployment Rollback", "description": "Procedure for rolling back a bad deployment", "text": "1. Identify the failing deployment via CI/CD.\n2. Trigger rollback to the last known-good version.\n3. Verify error rates return to baseline." } }' ``` ```json { "runbook": { "name": "runbooks/deployment-rollback", "displayName": "Deployment Rollback", "description": "Procedure for rolling back a bad deployment", "text": "1. Identify the failing deployment via CI/CD.\n2. Trigger rollback to the last known-good version.\n3. Verify error rates return to baseline.", "createTime": "2024-08-10T09:01:00Z", "updateTime": "2024-08-10T09:01:00Z" } } ``` **3. List all runbooks** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/ListRunbooks" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "runbooks": [ { "name": "runbooks/high-error-rate-triage", "displayName": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "createTime": "2024-08-10T09:00:00Z", "updateTime": "2024-08-10T09:00:00Z" }, { "name": "runbooks/deployment-rollback", "displayName": "Deployment Rollback", "description": "Procedure for rolling back a bad deployment", "createTime": "2024-08-10T09:01:00Z", "updateTime": "2024-08-10T09:01:00Z" } ], "nextPageToken": "" } ``` ## Methods | Method | Description | |:-------|:------------| | [CreateRunbook](#createrunbook) | Create a new runbook | | [GetRunbook](#getrunbook) | Retrieve a runbook by name | | [UpdateRunbook](#updaterunbook) | Update an existing runbook | | [DeleteRunbook](#deleterunbook) | Soft-delete a runbook | | [ListRunbooks](#listrunbooks) | List runbooks with filtering and pagination | --- ## CreateRunbook Create a new runbook. ``` POST /firetiger.runbooks.v1.RunbooksService/CreateRunbook ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `runbook_id` | string | Yes | ID for the new runbook (alphanumeric, hyphens, underscores) | | `runbook` | [Runbook](types/runbook.txt) | Yes | The runbook to create | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/CreateRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "runbook_id": "high-error-rate-triage", "runbook": { "display_name": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "text": "1. Query the database for recent deployments.\n2. Check HTTP error rates via Prometheus.\n3. If a recent deploy correlates, escalate to the owning team.", "connections": [ { "name": "connections/prod-postgres", "enabled_tools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabled_tools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ] } }' ``` **Response** ```json { "runbook": { "name": "runbooks/high-error-rate-triage", "displayName": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "text": "1. Query the database for recent deployments.\n2. Check HTTP error rates via Prometheus.\n3. If a recent deploy correlates, escalate to the owning team.", "connections": [ { "name": "connections/prod-postgres", "enabledTools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabledTools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ], "createTime": "2024-08-10T09:00:00Z", "updateTime": "2024-08-10T09:00:00Z" } } ``` --- ## GetRunbook Retrieve a runbook by name. ``` POST /firetiger.runbooks.v1.RunbooksService/GetRunbook ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the runbook | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/GetRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "runbooks/high-error-rate-triage"}' ``` --- ## UpdateRunbook Update an existing runbook. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.runbooks.v1.RunbooksService/UpdateRunbook ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `runbook` | [Runbook](types/runbook.txt) | Yes | The runbook with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/UpdateRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "runbook": { "name": "runbooks/high-error-rate-triage", "description": "Updated triage steps for elevated error rates, now includes log correlation" }, "update_mask": "description" }' ``` --- ## DeleteRunbook Soft-delete a runbook. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. ``` POST /firetiger.runbooks.v1.RunbooksService/DeleteRunbook ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the runbook to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/DeleteRunbook" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "runbooks/high-error-rate-triage"}' ``` --- ## ListRunbooks List runbooks with optional filtering and pagination. ``` POST /firetiger.runbooks.v1.RunbooksService/ListRunbooks ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression | | `order_by` | string | No | Field to sort by (e.g. `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted runbooks | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.runbooks.v1.RunbooksService/ListRunbooks" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"page_size": 25}' ``` **Response** ```json { "runbooks": [ { "name": "runbooks/high-error-rate-triage", "displayName": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "createTime": "2024-08-10T09:00:00Z", "updateTime": "2024-08-10T09:00:00Z" } ], "nextPageToken": "" } ``` ## Triggers Triggers define how and when agent sessions are created. A trigger is bound to a specific agent and can fire on a cron schedule, after a deployment, or only when manually invoked. Disabled cron triggers are skipped by the scheduler, but manual triggers can always be invoked regardless of the `enabled` flag. **Service**: `firetiger.triggers.v1.TriggersService` **Resource name pattern**: `triggers/{trigger_id}` **Access**: Read-write **Resource type**: [Trigger](types/trigger.txt) ## Example flow Create a manual trigger linked to an agent, then invoke it to kick off a session. **1. Create a manual trigger** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/CreateTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "trigger_id": "incident-runbook", "trigger": { "display_name": "Incident Runbook", "description": "Manually invoked to run an incident response playbook", "agent": "agents/incident-responder", "configuration": { "manual": {} }, "enabled": true } }' ``` ```json { "trigger": { "name": "triggers/incident-runbook", "displayName": "Incident Runbook", "description": "Manually invoked to run an incident response playbook", "agent": "agents/incident-responder", "configuration": { "manual": {} }, "enabled": true, "createTime": "2024-08-01T12:00:00Z", "updateTime": "2024-08-01T12:00:00Z" } } ``` **2. Invoke the trigger** Pass a `message` that becomes the initial user activity in the new agent session. The response includes the trigger and the name of the newly created session. ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/InvokeTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "name": "triggers/incident-runbook", "message": "There is an ongoing incident affecting checkout. Run the incident response playbook." }' ``` ```json { "trigger": { "name": "triggers/incident-runbook", "displayName": "Incident Runbook", "description": "Manually invoked to run an incident response playbook", "agent": "agents/incident-responder", "configuration": { "manual": {} }, "enabled": true, "createTime": "2024-08-01T12:00:00Z", "updateTime": "2024-08-01T12:00:00Z" }, "session": "agents/incident-responder/sessions/ses-abc123" } ``` **3. Check the session** Use the session name from the InvokeTrigger response to read messages via the [Agent Service](agents.txt#read). ```bash curl -X POST "{{ site.api_url }}/firetiger.nxagent.v2.AgentService/Read" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"session": "agents/incident-responder/sessions/ses-abc123", "session_offset": 0}' ``` ## Methods | Method | Description | |:-------|:------------| | [CreateTrigger](#createtrigger) | Create a new trigger | | [GetTrigger](#gettrigger) | Retrieve a trigger by name | | [UpdateTrigger](#updatetrigger) | Update an existing trigger | | [DeleteTrigger](#deletetrigger) | Soft-delete a trigger | | [ListTriggers](#listtriggers) | List triggers with filtering and pagination | | [InvokeTrigger](#invoketrigger) | Manually invoke a trigger to create an agent session | --- ## CreateTrigger Create a new trigger. ``` POST /firetiger.triggers.v1.TriggersService/CreateTrigger ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `trigger_id` | string | No | ID for the new trigger (alphanumeric, hyphens, underscores). Auto-generated if omitted. | | `trigger` | [Trigger](types/trigger.txt) | Yes | The trigger to create | **Example -- cron trigger** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/CreateTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "trigger_id": "daily-health-check", "trigger": { "display_name": "Daily Health Check", "description": "Runs a health check every morning at 9 AM Eastern", "agent": "agents/health-checker", "configuration": { "cron": { "schedule": "0 9 * * *", "timezone": "America/New_York" } }, "enabled": true } }' ``` **Example -- manual trigger** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/CreateTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "trigger_id": "incident-runbook", "trigger": { "display_name": "Incident Runbook", "description": "Manually invoked to run an incident response playbook", "agent": "agents/incident-responder", "configuration": { "manual": {} }, "enabled": true } }' ``` **Example -- post-deploy trigger** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/CreateTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "trigger_id": "post-deploy-smoke-test", "trigger": { "display_name": "Post-Deploy Smoke Test", "description": "Runs smoke tests 5 minutes after the release SHA lands in production", "agent": "agents/smoke-tester", "configuration": { "post_deploy": { "repository": "acme/backend", "environment": "production", "sha": "abc123def456", "delay": "300s" } }, "enabled": true } }' ``` **Response** ```json { "trigger": { "name": "triggers/daily-health-check", "displayName": "Daily Health Check", "description": "Runs a health check every morning at 9 AM Eastern", "agent": "agents/health-checker", "configuration": { "cron": { "schedule": "0 9 * * *", "timezone": "America/New_York" } }, "enabled": true, "createTime": "2024-08-01T12:00:00Z", "updateTime": "2024-08-01T12:00:00Z" } } ``` --- ## GetTrigger Retrieve a trigger by name. ``` POST /firetiger.triggers.v1.TriggersService/GetTrigger ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the trigger | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/GetTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "triggers/daily-health-check"}' ``` --- ## UpdateTrigger Update an existing trigger. Use `update_mask` to specify which fields to modify. ``` POST /firetiger.triggers.v1.TriggersService/UpdateTrigger ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `trigger` | [Trigger](types/trigger.txt) | Yes | The trigger with `name` set and updated fields | | `update_mask` | string | No | Comma-separated list of fields to update. If omitted, all provided fields are updated. | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/UpdateTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "trigger": { "name": "triggers/daily-health-check", "enabled": false }, "update_mask": "enabled" }' ``` --- ## DeleteTrigger Soft-delete a trigger. The resource will still be accessible via Get but excluded from List results unless `show_deleted` is set. ``` POST /firetiger.triggers.v1.TriggersService/DeleteTrigger ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the trigger to delete | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/DeleteTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"name": "triggers/daily-health-check"}' ``` --- ## ListTriggers List triggers with optional filtering and pagination. ``` POST /firetiger.triggers.v1.TriggersService/ListTriggers ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `filter` | string | No | [Filter](index.txt#filtering) expression (e.g. `enabled = true`, `agent = "agents/my-agent"`) | | `order_by` | string | No | Field to sort by (e.g. `display_name`, `create_time desc`) | | `page_size` | integer | No | Maximum results per page | | `page_token` | string | No | Token for the next page of results | | `show_deleted` | boolean | No | Include soft-deleted triggers | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/ListTriggers" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{"filter": "enabled = true", "page_size": 25}' ``` **Response** ```json { "triggers": [ { "name": "triggers/daily-health-check", "displayName": "Daily Health Check", "agent": "agents/health-checker", "configuration": { "cron": { "schedule": "0 9 * * *", "timezone": "America/New_York" } }, "enabled": true, "createTime": "2024-08-01T12:00:00Z", "updateTime": "2024-08-01T12:00:00Z" } ], "nextPageToken": "" } ``` --- ## InvokeTrigger Manually invoke a trigger, immediately creating a new agent session. This works for any trigger type -- cron, manual, or post-deploy -- and works regardless of the `enabled` flag. The `message` field becomes the initial user activity in the new session. ``` POST /firetiger.triggers.v1.TriggersService/InvokeTrigger ``` **Request body** | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `name` | string | Yes | Resource name of the trigger to invoke | | `message` | string | Yes | Message sent to the agent as the initial user activity in the new session | **Example** ```bash curl -X POST "{{ site.api_url }}/firetiger.triggers.v1.TriggersService/InvokeTrigger" \ -u "$USERNAME:$PASSWORD" \ -H "Content-Type: application/json" \ -d '{ "name": "triggers/incident-runbook", "message": "There is an ongoing incident affecting checkout. Run the incident response playbook." }' ``` **Response** ```json { "trigger": { "name": "triggers/incident-runbook", "displayName": "Incident Runbook", "description": "Manually invoked to run an incident response playbook", "agent": "agents/incident-responder", "configuration": { "manual": {} }, "enabled": true, "createTime": "2024-08-01T12:00:00Z", "updateTime": "2024-08-05T09:15:00Z" }, "session": "agents/incident-responder/sessions/ses-abc123" } ``` ## Types Reference documentation for all resource types, enums, and shared types used across the Firetiger API. ### Agent | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`agents/{id}`) | | `title` | string | | Human-readable title for the agent | | `description` | string | | Description of what this agent does | | `prompt` | string | | Initial prompt used to start agent sessions | | `connections` | [AgentConnection](#agent-connection)[] | | Connections and their enabled tools for this agent | | `state` | [AgentState](#agent-state) | | The operational state of the agent | | `tags` | string[] | | Tags assigned to this agent (`tags/{tag_id}`). Cannot include system tags. | | `plan_session` | string | | The session that planned this agent, if created by an agent session (`agents/{agent}/sessions/{session}`) | | `system` | boolean | OUTPUT_ONLY | Whether this is a system agent (auto-created, not user-managed) | | `created_by` | string | OUTPUT_ONLY | The ID of the user who created this agent | | `create_time` | timestamp | OUTPUT_ONLY | When the agent was created | | `update_time` | timestamp | OUTPUT_ONLY | When the agent was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the agent was soft-deleted (null if active) | **Example** ```json { "name": "agents/error-rate-monitor", "title": "Error Rate Monitor", "description": "Monitors services for abnormal error rates and escalation patterns.", "prompt": "You are a monitoring agent for production services. Your job is to detect abnormal errors...", "connections": [ { "name": "connections/prod-postgres", "enabledTools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabledTools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ], "tags": ["tags/production", "tags/monitoring"], "state": "AGENT_STATE_ON", "system": false, "createTime": "2026-02-21T20:37:33.623697Z", "updateTime": "2026-02-21T20:40:06.610686Z" } ``` ## Agent State | Value | Description | |:------|:------------| | `AGENT_STATE_UNSPECIFIED` | Default value, not used | | `AGENT_STATE_ON` | Agent is active and running | | `AGENT_STATE_OFF` | Agent is disabled | | `AGENT_STATE_REVIEW_REQUIRED` | Agent requires human review before activation | | `AGENT_STATE_RECOMMENDED` | Agent is recommended but not yet activated | ## Agent Connection | Field | Type | Description | |:------|:-----|:------------| | `name` | string | Resource name of the connection (`connections/{connection}`) | | `enabled_tools` | [Tool](connection.txt#tool)[] | List of tools enabled for this agent from this connection. If empty, all tools configured on the connection are enabled. | ### Session | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`agents/{agent}/sessions/{session}`) | | `associated_resources` | string[] | | Resource names linked to this session (e.g. `objectives/abc`, `incidents/xyz`) | | `create_time` | timestamp | OUTPUT_ONLY | When the session was created | | `update_time` | timestamp | OUTPUT_ONLY | When the session was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the session was soft-deleted (null if active) | **Example** ```json { "name": "agents/objectives-evaluator/sessions/ses-00ab12cd34ef", "associatedResources": [ "objectives/obj-daily-uptime", "objectives/obj-daily-uptime/evaluations/eval-56gh78ij" ], "createTime": "2026-02-13T01:02:36.105551Z", "updateTime": "2026-02-13T01:02:36.105551Z" } ``` ## Session Description A richer, read-only view of a session including runtime state from the execution engine. | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `session` | [Session](#session) | OUTPUT_ONLY | The session being described | | `status` | [Session Status](#session-status) | OUTPUT_ONLY | Current execution status of the session | | `session_length` | integer | OUTPUT_ONLY | Number of messages in the session | | `last_message` | timestamp | OUTPUT_ONLY | Timestamp of the last message in the session | | `conclusion` | [SessionConclusion](#session-conclusion) | OUTPUT_ONLY | Conclusion of the session, if the agent has concluded | ## Session Status | Value | Description | |:------|:------------| | `STATUS_UNSPECIFIED` | Session state is undefined (session has no objects) | | `STATUS_EXECUTING` | Agent is currently executing | | `STATUS_WAITING` | Agent is waiting (paused or idle) | ## Session Conclusion The conclusion of a completed session. Exactly one of `done` or `abort` will be set. | Field | Type | Description | |:------|:-----|:------------| | `done` | [Done](#done) | The agent completed its task | | `abort` | [Abort](#abort) | The agent aborted before completing | ### Done | Field | Type | Description | |:------|:-----|:------------| | `message` | string | Summary of what the agent accomplished | | `issues` | [ConclusionIssue](#conclusion-issue)[] | Issues discovered during the session | ### Abort | Field | Type | Description | |:------|:-----|:------------| | `message` | string | Explanation of why the agent aborted | ### Conclusion Issue An issue discovered by the agent during a session. | Field | Type | Description | |:------|:-----|:------------| | `title` | string | Short title for the issue | | `description` | string | Detailed description of the issue | ## Artifact | Field | Type | Description | |:------|:-----|:------------| | `contents` | bytes | Raw bytes of the artifact | ### Connection | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`connections/{id}`) | | `connection_type` | [ConnectionType](#connection-type) | REQUIRED | Type of external system (e.g. `CONNECTION_TYPE_POSTGRES`, `CONNECTION_TYPE_SLACK`) | | `display_name` | string | REQUIRED | Human-readable name for the connection | | `description` | string | REQUIRED | Description of what this connection provides | | `create_time` | timestamp | OUTPUT_ONLY | When the connection was created | | `update_time` | timestamp | OUTPUT_ONLY | When the connection was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the connection was soft-deleted (null if active) | | `secret_id` | string | | ID of the secret storing full connection details | | `connection_details` | [ConnectionDetails](#connection-details) | REQUIRED | Connection-specific configuration | | `tool_configurations` | [ToolConfiguration](#tool-configuration)[] | | Which tools are enabled for this connection | | `read_only` | boolean | OUTPUT_ONLY | Whether the connection is system-managed and cannot be edited | | `shell_environment` | [ShellEnvironment](#shell-environment) | OUTPUT_ONLY | Shell prompt information (populated on Get only) | | `connection_status` | [Status](#status) | OUTPUT_ONLY | Operational status of credential resolution (nil or OK means healthy) | **Example** ```json { "name": "connections/prod-iceberg", "connectionType": "CONNECTION_TYPE_ICEBERG", "displayName": "Production Iceberg", "description": "Iceberg connection for production data lake", "createTime": "2026-02-07T08:28:56.588670Z", "updateTime": "2026-02-07T08:28:56.588670Z", "secretId": "conn_778f2937dc19466086069ee42d234b0a" } ``` ## Connection Type | Value | Description | |:------|:------------| | `CONNECTION_TYPE_POSTGRES` | PostgreSQL database | | `CONNECTION_TYPE_HTTP` | Generic HTTP API | | `CONNECTION_TYPE_GOOGLE_POSTMASTER` | Google Postmaster Tools | | `CONNECTION_TYPE_PYLON` | Pylon customer support platform | | `CONNECTION_TYPE_GITHUB` | GitHub App installation | | `CONNECTION_TYPE_SLACK` | Slack workspace | | `CONNECTION_TYPE_PROMQL` | PromQL-compatible Prometheus API | | `CONNECTION_TYPE_LINEAR` | Linear project management | | `CONNECTION_TYPE_AWS` | AWS (IAM role assumption or static credentials) | | `CONNECTION_TYPE_GCP` | GCP (service account authentication) | | `CONNECTION_TYPE_CLICKHOUSE` | ClickHouse database | | `CONNECTION_TYPE_MYSQL` | MySQL database | | `CONNECTION_TYPE_ICEBERG` | Apache Iceberg REST catalog | | `CONNECTION_TYPE_DATADOG` | Datadog observability platform | | `CONNECTION_TYPE_INCIDENT_IO` | incident.io webhook integration | | `CONNECTION_TYPE_PAGERDUTY` | PagerDuty incident management | | `CONNECTION_TYPE_OPENAPI` | OpenAPI-described REST API | | `CONNECTION_TYPE_CLERK` | Clerk user management and authentication | | `CONNECTION_TYPE_VANTA` | Vanta compliance and security automation | ## Tool Each connection type supports a set of tools that agents can use. The `enabled_tools` field on [AgentConnection](agent.txt#agent-connection) and [RunbookConnection](runbook.txt#runbook-connection) references values from this enum. | Value | Description | |:------|:------------| | `TOOL_POSTGRES_QUERY` | Execute a read-only SQL query against PostgreSQL | | `TOOL_POSTGRES_WRITE_QUERY` | Execute a read-write SQL query against PostgreSQL | | `TOOL_HTTP_REQUEST` | Make an HTTP request | | `TOOL_GITHUB_SEARCH_CODE` | Search code in GitHub repositories | | `TOOL_GITHUB_GET_FILE` | Get file contents from a GitHub repository | | `TOOL_GITHUB_LIST_DIRECTORY` | List files in a GitHub repository directory | | `TOOL_GITHUB_GET_PR` | Get a GitHub pull request | | `TOOL_GITHUB_GET_ISSUE` | Get a GitHub issue | | `TOOL_GITHUB_PULL_REQUEST_SEARCH` | Search GitHub pull requests | | `TOOL_GITHUB_CREATE_ISSUE` | Create a GitHub issue | | `TOOL_GITHUB_ADD_ISSUE_COMMENT` | Add a comment to a GitHub issue | | `TOOL_GITHUB_LIST_ISSUES` | List GitHub issues | | `TOOL_GITHUB_CREATE_PR_COMMENT` | Add a comment to a GitHub pull request | | `TOOL_GITHUB_LIST_PR_COMMENTS` | List comments on a GitHub pull request | | `TOOL_GITHUB_LIST_PR_REVIEWS` | List reviews on a GitHub pull request | | `TOOL_GITHUB_LIST_ORGANIZATION_MEMBERS` | List members of a GitHub organization | | `TOOL_GITHUB_LIST_REPOS` | List repositories in a GitHub organization | | `TOOL_PROMQL_QUERY` | Execute an instant PromQL query | | `TOOL_PROMQL_QUERY_RANGE` | Execute a range PromQL query | | `TOOL_PROMQL_LABEL_VALUES` | Get label values from Prometheus | | `TOOL_PROMQL_SERIES` | Get time series from Prometheus | | `TOOL_GOOGLE_POSTMASTER_LIST_DOMAINS` | List domains in Google Postmaster Tools | | `TOOL_GOOGLE_POSTMASTER_GET_TRAFFIC_STATS` | Get traffic stats from Google Postmaster Tools | | `TOOL_PYLON_LIST_ISSUES` | List issues from Pylon | | `TOOL_SLACK_SEND_MESSAGE` | Send a message in Slack | | `TOOL_FIRETIGER_QUERY` | Query Firetiger's data lake | | `TOOL_FIRETIGER_CODEBASE_SEARCH` | Search code across configured repositories | | `TOOL_LINEAR_LIST_ISSUES` | List issues from Linear | | `TOOL_LINEAR_LIST_USERS` | List users from Linear | | `TOOL_CLICKHOUSE_QUERY` | Execute a query against ClickHouse | | `TOOL_MYSQL_QUERY` | Execute a read-only query against MySQL | | `TOOL_ICEBERG_QUERY` | Query an Apache Iceberg table | | `TOOL_DATADOG_QUERY_METRICS` | Query metrics from Datadog | | `TOOL_DATADOG_QUERY_LOGS` | Query logs from Datadog | | `TOOL_OPENAPI_REQUEST` | Make HTTP requests to an OpenAPI-described API | | `TOOL_OPENAPI_SCHEMA` | Introspect the OpenAPI spec for available endpoints and schemas | ## Tool Configuration Controls whether a specific tool is enabled on a connection. | Field | Type | Description | |:------|:-----|:------------| | `tool` | [Tool](#tool) | The tool being configured | | `is_enabled` | boolean | Whether this tool is enabled | ## Connection Details Connection-specific configuration. This is a union type -- exactly one variant is set, matching the connection's `connection_type`. The fields vary by connection type (e.g. host/port/database for PostgreSQL, base URL and headers for HTTP). Refer to the connection creation UI or `ftops api connections` for the fields available for each type. ### HTTP Connection Details | Field | Type | Description | |:------|:-----|:------------| | `base_url` | string | Base URL for HTTP requests | | `allowed_routes` | string[] | Allowed route patterns | | `headers` | map\ | Non-auth headers included in every request (e.g. `Content-Type`, `X-Tenant-ID`) | | `max_response_size_bytes` | uint64 | Maximum response size in bytes | | `timeout_seconds` | uint32 | Request timeout in seconds | | `oauth_client_credentials` | [OAuthClientCredentials](#oauth-client-credentials) | OAuth 2.0 Client Credentials grant (oneof `auth`) | | `bearer_token` | [HttpBearerAuth](#bearer-token) | Static Bearer token (oneof `auth`) | | `basic_auth` | [HttpBasicAuth](#basic-auth) | HTTP Basic authentication (oneof `auth`) | | `static_headers` | [HttpAuthStaticHeaders](#static-headers) | Auth via raw headers (oneof `auth`) | Authentication is configured via the `auth` oneof — set exactly one of the four auth fields above. #### OAuth Client Credentials The resolver automatically obtains and refreshes an OAuth 2.0 access token using the client credentials grant. The token is injected as an `Authorization: Bearer` header on each request. | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `token_url` | string | REQUIRED | Token endpoint URL (must use HTTPS, e.g. `https://api.vanta.com/oauth/token`) | | `client_id` | string | | OAuth client ID (returned in responses) | | `client_secret` | string | INPUT_ONLY | OAuth client secret (not returned in responses) | | `scopes` | string | | Optional space-separated scopes to request | | `extra_params` | map\ | | Optional additional form parameters for the token request (e.g. `audience`) | | `access_token` | string | OUTPUT_ONLY | Current access token (populated by the resolver) | | `token_expires_at` | timestamp | OUTPUT_ONLY | When the current access token expires | #### Bearer Token | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `token` | string | INPUT_ONLY | Bearer token value | #### Basic Auth | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `username` | string | | Username | | `password` | string | INPUT_ONLY | Password | #### Static Headers | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `headers` | map\ | INPUT_ONLY | Auth headers to include in every request | Non-auth `headers` can be used alongside any auth method (e.g. `X-Tenant-ID`). Auth headers are resolved from the `auth` field and merged into the request; do not duplicate auth headers in `headers`. ### OpenAPI Connection Details Connect to any REST API that publishes an OpenAPI (Swagger) specification. The agent can introspect the spec to discover endpoints and make authenticated requests. | Field | Type | Description | |:------|:-----|:------------| | `spec_url` | string | URL to fetch the OpenAPI specification (JSON or YAML) | | `server_url` | string | Base URL of the API server. If empty, derived from the spec's `servers[0].url` | | `oauth_client_credentials` | [OAuthClientCredentials](#oauth-client-credentials) | OAuth 2.0 Client Credentials grant (oneof `auth`) | | `bearer_token` | [HttpBearerAuth](#bearer-token) | Static Bearer token (oneof `auth`) | | `basic_auth` | [HttpBasicAuth](#basic-auth) | HTTP Basic authentication (oneof `auth`) | Authentication is configured via the `auth` oneof — set exactly one of the three auth fields above. The auth types reuse the same messages as [HTTP Connection Details](#http-connection-details). When `server_url` is omitted, the resolver fetches the spec and extracts the base URL from `servers[0].url`, resolving relative paths (e.g. `/v1`) against the spec URL. **Example** ```json { "connectionType": "CONNECTION_TYPE_OPENAPI", "displayName": "Vanta API", "description": "Vanta compliance platform API", "connectionDetails": { "openapi": { "specUrl": "https://firetiger-public.s3.us-west-2.amazonaws.com/connections/vanta/openapi.json", "serverUrl": "https://api.vanta.com/v1", "oauthClientCredentials": { "tokenUrl": "https://api.vanta.com/oauth/token", "clientId": "my-client-id", "clientSecret": "my-client-secret", "scopes": "vanta-api.all:read" } } } } ``` ### Clerk Connection Details Connect to the Clerk Backend API for user management and authentication. Uses a Bearer token (Clerk secret key) for auth. | Field | Type | Description | |:------|:-----|:------------| | `bearer_token` | [HttpBearerAuth](#bearer-token) | Clerk Secret Key (`sk_live_...` or `sk_test_...`) as Bearer token (oneof `auth`) | Authentication is configured via the `auth` oneof. The Clerk connection automatically configures the OpenAPI spec URL (`https://clerk.com/docs/reference/spec/bapi/2025-11-10`) and server URL (`https://api.clerk.com`). Agents use the `openapi_schema` and `openapi_request` tools to interact with the API. **Example** ```json { "connectionType": "CONNECTION_TYPE_CLERK", "displayName": "Clerk", "description": "Clerk user management and authentication API", "connectionDetails": { "clerk": { "bearerToken": { "token": "sk_live_..." } } } } ``` ### Vanta Connection Details Connect to the Vanta API for compliance and security automation. Uses OAuth 2.0 Client Credentials for authentication. | Field | Type | Description | |:------|:-----|:------------| | `oauth_client_credentials` | [OAuthClientCredentials](#oauth-client-credentials) | OAuth 2.0 Client Credentials for Vanta API (oneof `auth`) | Authentication is configured via the `auth` oneof. The Vanta connection automatically configures the OpenAPI spec URL (`https://firetiger-public.s3.us-west-2.amazonaws.com/connections/vanta/openapi.json`) and server URL (`https://api.vanta.com/v1`). Agents use the `openapi_schema` and `openapi_request` tools to interact with the API. **Example** ```json { "connectionType": "CONNECTION_TYPE_VANTA", "displayName": "Vanta", "description": "Vanta compliance and security automation API", "connectionDetails": { "vanta": { "oauthClientCredentials": { "tokenUrl": "https://api.vanta.com/oauth/token", "clientId": "my-client-id", "clientSecret": "my-client-secret", "scopes": "vanta-api.all:read" } } } } ``` ## Shell Environment Shell prompt information for the connection, populated only on Get requests. | Field | Type | Description | |:------|:-----|:------------| | `prompt` | string | Shell prompt text for interactive sessions | ## Status Operational status of the connection's credential resolution, following the [google.rpc.Status](https://cloud.google.com/apis/design/errors#error_model) format. | Field | Type | Description | |:------|:-----|:------------| | `code` | integer | Status code (0 means OK) | | `message` | string | Human-readable error message (empty when healthy) | ### Customer | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`customers/{customer_id}`) | | `external_id` | string | REQUIRED | Identifier from your telemetry system, used to filter this customer's data in logs. Examples: `"acme-corp"`, `"b81cb7725908"` | | `id` | string | OUTPUT_ONLY | The `{customer_id}` portion of the resource name (SHA-256 hash of `external_id`) | | `display_name` | string | | Human-readable name for the customer | | `description` | string | | Description of the customer and their use case | | `runbook` | string | | Instructions for investigating issues with this customer | | `workload_summary` | string | | AI-generated summary of the customer's workload patterns | | `create_time` | timestamp | OUTPUT_ONLY | When the customer was created | | `update_time` | timestamp | OUTPUT_ONLY | When the customer was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the customer was soft-deleted (null if active) | | `purge_time` | timestamp | OUTPUT_ONLY | Earliest time the customer can be permanently purged | **Example** ```json { "name": "customers/cso47xax", "externalId": "acme-corp", "displayName": "Acme Corp", "description": "Enterprise customer with high request volume", "workloadSummary": "High throughput tenant with 835K requests/6h (~39 req/s). Stable latency profile.", "createTime": "2025-10-10T18:07:55.847133Z", "updateTime": "2025-10-14T18:14:29.993442Z" } ``` ### Deployment | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`deployments/{id}`) | | `source` | [DeploymentSource](#deployment-source) | | Origin system that created this deployment event | | `status` | [DeploymentStatus](#deployment-status) | | Current status of the deployment (denormalized from latest status event) | | `labels` | map\ | | Flexible key-value dimensions for categorizing deployments | | `create_time` | timestamp | OUTPUT_ONLY | When the deployment record was created | | `update_time` | timestamp | OUTPUT_ONLY | When the deployment record was last updated | | `delete_time` | timestamp | OUTPUT_ONLY | When the deployment was soft-deleted (null if active) | | `start_time` | timestamp | | When the deployment actually started executing | | `complete_time` | timestamp | | When the deployment completed (success, failure, or error) | | `external_id` | string | | External identifier from the source system (e.g. GitHub deployment ID) | | `external_url` | string | | URL to view this deployment in the source system | | `description` | string | | Human-readable description or title of the deployment | **Example** ```json { "name": "deployments/8981264b-cf59-434c-95a0-1ec58b502226", "source": "DEPLOYMENT_SOURCE_GITHUB", "status": "DEPLOYMENT_STATUS_SUCCESS", "labels": { "deployer": "octocat", "environment": "production", "ref": "main", "repository": "acme/backend", "sha": "acb26d1df10035fdde98ceb7f29d0e9276367fcb" }, "createTime": "2026-02-13T01:04:29.873715Z", "updateTime": "2026-02-13T01:08:40.953822Z", "startTime": "2026-02-13T01:04:28Z", "completeTime": "2026-02-13T01:08:39Z", "externalId": "gh-3831677370", "externalUrl": "https://github.com/acme/backend/deployments" } ``` Common labels auto-extracted from GitHub webhooks: | Label | Example | Description | |:------|:--------|:------------| | `repository` | `acme-corp/backend` | Repository full name | | `environment` | `production` | Deployment environment | | `ref` | `main` | Git reference (branch or tag) | | `sha` | `abc123...` | Commit SHA being deployed | | `deployer` | `octocat` | User who triggered the deployment | ## Deployment Source | Value | Description | |:------|:------------| | `DEPLOYMENT_SOURCE_UNSPECIFIED` | Default value, not used | | `DEPLOYMENT_SOURCE_GITHUB` | Deployment originated from GitHub | | `DEPLOYMENT_SOURCE_MANUAL` | Deployment was recorded manually | ## Deployment Status | Value | Description | |:------|:------------| | `DEPLOYMENT_STATUS_UNSPECIFIED` | Default value, not used | | `DEPLOYMENT_STATUS_PENDING` | Deployment is pending | | `DEPLOYMENT_STATUS_QUEUED` | Deployment is queued | | `DEPLOYMENT_STATUS_IN_PROGRESS` | Deployment is currently executing | | `DEPLOYMENT_STATUS_SUCCESS` | Deployment completed successfully | | `DEPLOYMENT_STATUS_FAILED` | Deployment failed | | `DEPLOYMENT_STATUS_ERROR` | Deployment encountered an error | | `DEPLOYMENT_STATUS_INACTIVE` | Deployment is inactive | ## Deployment Status Event **Resource name pattern**: `deployments/{deployment_id}/status-events/{status_event_id}` | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`deployments/{id}/status-events/{id}`) | | `deployment` | string | REQUIRED | Parent deployment resource name | | `status` | [DeploymentStatus](#deployment-status) | | The status at this point in time | | `description` | string | | Context for this status change | | `event_time` | timestamp | | When this status was recorded in the source system | | `external_url` | string | | URL to view this status event in the source system | | `create_time` | timestamp | OUTPUT_ONLY | When this status event record was created | | `update_time` | timestamp | OUTPUT_ONLY | When this status event record was last updated | | `delete_time` | timestamp | OUTPUT_ONLY | When this status event was soft-deleted (null if active) | --- ## Deployment Monitor Evaluation | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`deployment-monitor-evaluations/{id}`) | | `create_time` | timestamp | OUTPUT_ONLY | When the evaluation was created | | `update_time` | timestamp | OUTPUT_ONLY | When the evaluation was last updated | | `delete_time` | timestamp | OUTPUT_ONLY | When the evaluation was soft-deleted (null if active) | | `session_name` | string | | Reference to the agent session running this evaluation (`agents/{agent}/sessions/{session}`) | | `status` | [DeploymentMonitorEvaluationStatus](#deployment-monitor-evaluation-status) | | Current status of the evaluation | | `github_run_id` | integer | | GitHub Actions workflow run ID that triggered the deployment | | `environment` | string | | The environment being deployed to (e.g. `production`) | | `repository` | string | | Repository in `owner/name` format (e.g. `acme-corp/backend`) | | `head_sha` | string | | The commit SHA being deployed | | `base_sha` | string | | The base commit SHA (previous deployment) | | `pr_number` | integer | | PR number if this deployment is from a PR merge (0 if not) | | `deployment_time` | timestamp | | When the deployment started | | `summary` | string | | Summary of the monitoring period written by the agent on completion | | `overall_status` | string | | Overall outcome: `successful`, `warning`, or `incident` | ## Deployment Monitor Evaluation Status | Value | Description | |:------|:------------| | `DEPLOYMENT_MONITOR_EVALUATION_STATUS_UNSPECIFIED` | Default value, not used | | `DEPLOYMENT_MONITOR_EVALUATION_STATUS_RUNNING` | Evaluation is currently running | | `DEPLOYMENT_MONITOR_EVALUATION_STATUS_COMPLETED` | Evaluation has completed | ### Investigation | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`investigations/{id}`) | | `display_name` | string | | Human-readable display name for the investigation | | `description` | string | | Problem statement describing what to investigate | | `status` | [InvestigationStatus](#investigation-status) | OUTPUT_ONLY | Current execution status (set by the server) | | `created_by` | string | OUTPUT_ONLY | Authenticated user identifier | | `create_time` | timestamp | OUTPUT_ONLY | When the investigation was created | | `update_time` | timestamp | OUTPUT_ONLY | When the investigation was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the investigation was soft-deleted (null if active) | **Example** ```json { "name": "investigations/00077c084e17b0ec026a4b713a0f0dbc", "displayName": "User Login Error Investigation", "description": "A user is reporting they cannot log in to the UI. Check for authentication errors in recent logs.", "status": "INVESTIGATION_STATUS_EXECUTING", "createdBy": "user_2xK9mBqHn1pL4vR7wT3eYjZ8aFd", "createTime": "2025-12-15T16:33:31.693279Z", "updateTime": "2025-12-15T16:33:31.693279Z" } ``` ## Investigation Status | Value | Description | |:------|:------------| | `INVESTIGATION_STATUS_UNSPECIFIED` | Default value, not used | | `INVESTIGATION_STATUS_EXECUTING` | Investigation is actively executing | | `INVESTIGATION_STATUS_WAITING` | Investigation is waiting | ### Issue | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`issues/{id}`) | | `display_name` | string | | Short display name for the issue | | `description` | string | | Detailed description of the detected issue | | `session` | string | | Agent session that detected this issue | | `create_time` | timestamp | OUTPUT_ONLY | When the issue was created | | `update_time` | timestamp | OUTPUT_ONLY | When the issue was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the issue was soft-deleted (null if active) | | `suggested_known_issues` | string[] | | Known issues that might be related to this issue, populated by LLM-based retrieval when issue is created | **Example** ```json { "name": "issues/db80f50ddbf7", "displayName": "S3 Timeout Errors Escalating", "description": "datafile-optimizer-plan experiencing 2,839 errors/hour (+22.3% from previous hour), representing 71.2% of planner errors. Errors include 'context canceled' and 'operation error S3: HeadObject/GetObject, context deadline exceeded'.", "session": "agents/my-monitor/sessions/ses-abc123", "suggestedKnownIssues": ["known-issues/s3-timeouts", "known-issues/planner-errors"], "createTime": "2026-02-13T01:04:27.924994Z", "updateTime": "2026-02-13T01:04:27.924994Z" } ``` --- ## Issue Notification Policy | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`issue-notification-policies/{id}`) | | `description` | string | | Human-readable description of the policy | | `connections` | string[] | | List of connection resource names (`connections/{id}`) used for sending notifications | | `prompt` | string | | Instructions for the notification agent defining routing rules, channel selection, and formatting preferences | | `state` | [IssueNotificationPolicyState](#issue-notification-policy-state) | | Current state of the policy | | `review_reason` | string | | Explanation of why the policy needs review (populated when state is `REVIEW_REQUIRED`) | | `planner_session` | string | | Agent session managing the notification planner | | `create_time` | timestamp | OUTPUT_ONLY | When the policy was created | | `update_time` | timestamp | OUTPUT_ONLY | When the policy was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the policy was soft-deleted (null if active) | | `purge_time` | timestamp | OUTPUT_ONLY | When the policy is scheduled for permanent deletion | **Example** ```json { "name": "issue-notification-policies/default", "description": "Send notifications to Slack (#alerts) and create Linear issues for all known issues.", "connections": [ "connections/slack-workspace", "connections/linear-project" ], "prompt": "When a known issue is created or updated, send notifications using both channels...", "state": "ISSUE_NOTIFICATION_POLICY_STATE_ACTIVE", "plannerSession": "agents/issue-notification-planner-agent/sessions/ses-def456", "createTime": "2026-02-28T01:09:28.105790Z", "updateTime": "2026-03-04T01:34:50.035946Z" } ``` ## Issue Notification Policy State | Value | Description | |:------|:------------| | `ISSUE_NOTIFICATION_POLICY_STATE_UNSPECIFIED` | Default value, not used | | `ISSUE_NOTIFICATION_POLICY_STATE_ACTIVE` | Policy is active and will send notifications when issues are detected | | `ISSUE_NOTIFICATION_POLICY_STATE_REVIEW_REQUIRED` | Policy needs human review before it will send notifications | ### Known Issue | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`known-issues/{id}`) | | `title` | string | | Short title describing the known issue | | `context` | string | | Additional context about the issue (investigation notes, root cause, etc.) | | `human_description` | string | | Concise paragraph describing the problem, what's known, and recommended action | | `status` | [KnownIssueStatus](#known-issue-status) | | Current status of the known issue | | `impacted_objectives` | string[] | | List of objective resource names affected by this issue | | `incidents` | string[] | | List of incident resource names related to this issue | | `issues` | string[] | | List of issue resource names (`issues/{id}`) linked to this known issue | | `links` | string[] | | External URLs relevant to the issue (tickets, postmortems, etc.) | | `session` | string | | Expert agent session that owns this known issue (auto-created on create) | | `create_time` | timestamp | OUTPUT_ONLY | When the known issue was created | | `update_time` | timestamp | OUTPUT_ONLY | When the known issue was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the known issue was soft-deleted (null if active) | **Example** ```json { "name": "known-issues/7f2aeed20da8", "title": "Webhook 401 authentication failures with token timeouts", "context": "## Root Cause: API Token Instability - RESOLVED\n\nFix deployed Feb 26, token caching eliminated the issue...", "humanDescription": "Chronic API token failures (Feb 13-26, ~880 failures) RESOLVED. Fix deployed Feb 26 achieved 97% immediate reduction, 100% elimination verified over 96 hours.", "status": "KNOWN_ISSUE_STATUS_RESOLVED", "issues": [ "issues/789a4a343c01", "issues/eff5de83e6c4", "issues/d8c2e560c537" ], "links": [ "https://example.slack.com/archives/C09ABC123/p1771796025097359" ], "session": "agents/known-issues-expert/sessions/ses-abc123", "createTime": "2026-02-22T21:33:33.826036Z", "updateTime": "2026-03-02T02:02:34.440248Z" } ``` ## Known Issue Status | Value | Description | |:------|:------------| | `KNOWN_ISSUE_STATUS_UNSPECIFIED` | Default value, not used | | `KNOWN_ISSUE_STATUS_ACTIVE` | Issue needs attention and is being tracked | | `KNOWN_ISSUE_STATUS_RESOLVED` | Issue has been fixed | | `KNOWN_ISSUE_STATUS_MUTED` | Issue is acknowledged but deprioritized | ### Monitoring Plan | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`monitoring-plans/{id}`) | | `origin` | [GithubPrOrigin](#github-pr-origin) | | Metadata about the GitHub PR that triggered this plan | | `activation` | [ActivationTrigger](#activation-trigger) | | Activation trigger configuration including the merge commit SHA | | `plan_content` | string | | Prose document describing intended effect, unintended effects to watch for, and risk assessment | | `plan_summary` | string | | One-sentence plain-text summary of the plan (~150 characters max) | | `notification_channel` | string | | Notification channel for alerts (e.g., Slack channel name) | | `author_session` | string | | Reference to the author agent session (`agents/{agent}/sessions/{session}`) | | `create_time` | timestamp | OUTPUT_ONLY | When the plan was created | | `update_time` | timestamp | OUTPUT_ONLY | When the plan was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the plan was soft-deleted (null if active) | | `deployments` | [MonitoredDeployment](#monitored-deployment)[] | | Per-environment deployment monitoring state | | `last_check_time` | timestamp | | Timestamp of the most recent scheduler check across all environments | | `related_resources` | string[] | | Internal list of related resources discovered during planning | **Example** ```json { "name": "monitoring-plans/f045b69d-8b64-43fb-9601-0d3118772da9", "origin": { "repository": "acme/backend", "prNumber": 3751, "prUrl": "https://github.com/acme/backend/pull/3751", "prTitle": "feat(ui): add support link to app", "prAuthor": "octocat" }, "activation": { "mergeSha": "17078c805a9fb991a09283f41b5c29ce70269028" }, "planContent": "# Monitoring Plan: Add Support Link\n\n## Risk Assessment: MINIMAL\nFrontend-only change...", "planSummary": "Add support mailto link to user dropdown menu - minimal risk frontend change", "authorSession": "agents/plan-author/sessions/ses-abc123", "createTime": "2026-02-17T22:00:01.717128Z", "updateTime": "2026-02-27T21:11:22.041370Z", "deployments": [ { "environment": "production", "deployment": "deployments/2cdaaa4f-3baa-4aa8-8cd9-74b3f663c5ef", "deployTime": "2026-02-17T22:18:04Z", "intendedEffectConfirmed": true, "outcome": "MONITORING_OUTCOME_NO_ISSUE", "completeTime": "2026-02-18T01:46:06.188498Z" } ] } ``` ## GitHub PR Origin | Field | Type | Description | |:------|:-----|:------------| | `repository` | string | Repository in org/repo format (e.g., `acme-corp/backend`) | | `pr_number` | integer | Pull request number | | `pr_url` | string | Full URL to the PR (used as deduplication key) | | `head_sha` | string | PR HEAD SHA at plan creation time | | `installation_id` | integer | GitHub App installation ID | | `pr_title` | string | PR title at plan creation time | | `pr_author` | string | GitHub login of the PR author | ## Activation Trigger | Field | Type | Description | |:------|:-----|:------------| | `merge_sha` | string | Merge commit SHA to watch for. Set when the PR merges; empty while PR is open. | | `environments` | string[] | Only activate for these environments (e.g., `["production"]`). If empty, activates for all. | ## Monitored Deployment | Field | Type | Description | |:------|:-----|:------------| | `environment` | string | The environment being monitored (e.g., `staging`, `production`) | | `deployment` | string | Reference to the deployment resource (`deployments/{deployment}`) | | `deploy_time` | timestamp | Deploy time from the Deployment resource | | `intended_effect_confirmed` | boolean | Whether the intended effect has been confirmed for this environment | | `outcome` | [MonitoringOutcome](#monitoring-outcome) | Outcome of monitoring for this environment | | `known_issue` | string | Reference to the known issue if outcome is `ISSUE_DETECTED` (`known-issues/{id}`) | | `complete_time` | timestamp | When monitoring for this environment completed | ## Monitoring Outcome | Value | Description | |:------|:------------| | `MONITORING_OUTCOME_UNSPECIFIED` | Default value, not used | | `MONITORING_OUTCOME_NO_ISSUE` | No issues detected during monitoring | | `MONITORING_OUTCOME_ISSUE_DETECTED` | An issue was detected during monitoring | --- ## Monitoring Run > MonitoringRunService is a legacy service. New monitoring state is stored directly on MonitoringPlan.deployments. | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`monitoring-plans/{plan}/runs/{run}`) | | `environment` | string | REQUIRED | The environment being monitored (e.g., `staging`, `production`) | | `deployment` | string | | Reference to the deployment that triggered this run (`deployments/{deployment}`) | | `status` | [MonitoringRunStatus](#monitoring-run-status) | | Current status of the monitoring run | | `outcome` | [MonitoringRunOutcome](#monitoring-run-outcome) | | Outcome of the monitoring run (set when status is COMPLETED or TIMED_OUT) | | `known_issue` | string | | Reference to the known issue if outcome is `ISSUE_DETECTED` (`known-issues/{id}`) | | `intended_effect_confirmed` | boolean | | Whether the intended effect has been confirmed | | `activate_time` | timestamp | | When the monitoring run was activated (deployment detected) | | `complete_time` | timestamp | | When the monitoring run completed | | `last_check_time` | timestamp | | When the last monitoring check ran | | `create_time` | timestamp | OUTPUT_ONLY | When the run was created | | `update_time` | timestamp | OUTPUT_ONLY | When the run was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the run was soft-deleted (null if active) | ## Monitoring Run Status | Value | Description | |:------|:------------| | `MONITORING_RUN_STATUS_UNSPECIFIED` | Default value, not used | | `MONITORING_RUN_STATUS_RUNNING` | Monitoring is actively running | | `MONITORING_RUN_STATUS_COMPLETED` | Monitoring has completed | | `MONITORING_RUN_STATUS_TIMED_OUT` | Monitoring timed out before completing | ## Monitoring Run Outcome | Value | Description | |:------|:------------| | `MONITORING_RUN_OUTCOME_UNSPECIFIED` | Default value, not used | | `MONITORING_RUN_OUTCOME_NO_ISSUE` | No issues detected during the run | | `MONITORING_RUN_OUTCOME_ISSUE_DETECTED` | An issue was detected during the run | ### Note | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`notes/{id}`) | | `display_name` | string | | Human-readable name for the note | | `notes` | string | | Free-form note content | | `description` | string | | Additional description or summary | | `tool_name` | string | | Name of the tool that produced this note | | `tool_args` | object | | Arguments passed to the tool (JSON object) | | `create_time` | timestamp | OUTPUT_ONLY | When the note was created | | `update_time` | timestamp | OUTPUT_ONLY | When the note was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the note was soft-deleted (null if active) | **Example** ```json { "name": "notes/c858d27932ef", "displayName": "Check CLS Threshold Violations", "description": "Query to detect CLS values exceeding the 0.1 threshold in the last hour from browser logs.", "toolName": "query", "toolArgs": { "sql": "SELECT time, attributes.page.path as page_path, CAST(attributes.web_vital.value AS DOUBLE) as cls_score FROM \"opentelemetry/logs/browser\" WHERE time >= CURRENT_TIMESTAMP - INTERVAL '1 hour' AND attributes.web_vital.name = 'CLS' AND attributes.web_vital.value IS NOT NULL" }, "createTime": "2025-12-02T19:26:03.311886Z", "updateTime": "2026-01-21T23:24:41.583126Z" } ``` ### Runbook | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`runbooks/{id}`) | | `display_name` | string | | Human-readable name for the runbook | | `description` | string | | Short description of what the runbook is for | | `text` | string | | The full runbook content with instructions for the agent | | `connections` | [RunbookConnection](#runbook-connection)[] | | Connections and tools available to the agent while executing this runbook | | `session_name` | string | | Agent session that created or manages this runbook (`agents/{agent}/sessions/{session}`) | | `create_time` | timestamp | OUTPUT_ONLY | When the runbook was created | | `update_time` | timestamp | OUTPUT_ONLY | When the runbook was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the runbook was soft-deleted (null if active) | **Example** ```json { "name": "runbooks/high-error-rate-triage", "displayName": "High Error Rate Triage", "description": "Steps for triaging elevated error rates on production services", "text": "1. Query the database for recent deployments.\n2. Check HTTP error rates via Prometheus.\n3. If a recent deploy correlates, escalate to the owning team.", "connections": [ { "name": "connections/prod-postgres", "enabledTools": ["TOOL_POSTGRES_QUERY"] }, { "name": "connections/prod-prometheus", "enabledTools": ["TOOL_PROMQL_QUERY", "TOOL_PROMQL_QUERY_RANGE"] } ], "createTime": "2024-08-10T09:00:00Z", "updateTime": "2024-08-10T09:00:00Z" } ``` ## Runbook Connection | Field | Type | Description | |:------|:-----|:------------| | `name` | string | Resource name of the connection (`connections/{id}`) | | `enabled_tools` | [Tool](connection.txt#tool)[] | Which tools from this connection the agent may use (e.g. `TOOL_POSTGRES_QUERY`, `TOOL_HTTP_REQUEST`) | ### Tag | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`tags/{id}`) | | `display_name` | string | REQUIRED | Human-readable name shown in the UI | | `description` | string | | Optional description of the tag | | `color` | string | | Hex color string (e.g., `#5E6AD2`). Ignored for system tags. | | `system` | boolean | OUTPUT_ONLY | True for `firetiger:*` tags (set by server) | | `create_time` | timestamp | OUTPUT_ONLY | When the tag was created | | `update_time` | timestamp | OUTPUT_ONLY | When the tag was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the tag was soft-deleted (null if active) | **Example** ```json { "name": "tags/production", "displayName": "Production", "description": "Agents monitoring production systems", "color": "#5E6AD2", "createTime": "2024-06-15T14:30:00Z", "updateTime": "2024-06-15T14:30:00Z" } ``` ## System tags System tags have names prefixed with `firetiger:` and are created by the system. They: - Have `system` set to `true` - Cannot be created, updated, or deleted via the API - Are always displayed in grey in the UI (the `color` field is ignored) **Example system tag** ```json { "name": "tags/firetiger:monitoring", "displayName": "Monitoring", "system": true, "createTime": "2024-01-01T00:00:00Z", "updateTime": "2024-01-01T00:00:00Z" } ``` ### Trigger | Field | Type | Behavior | Description | |:------|:-----|:---------|:------------| | `name` | string | OUTPUT_ONLY | Resource name (`triggers/{id}`) | | `display_name` | string | | Human-readable name for the trigger | | `description` | string | | Description of what this trigger does | | `agent` | string | REQUIRED | The agent to create sessions for. Format: `agents/{agent}` | | `configuration` | [TriggerConfiguration](#trigger-configuration) | | Determines trigger type and behavior | | `enabled` | boolean | | Whether the trigger is enabled. Disabled cron triggers are not executed. Manual triggers can always be invoked regardless of this setting. | | `activation_state` | [TriggerActivationState](#trigger-activation-state) | OUTPUT_ONLY | Runtime activation state. Currently only set for post_deploy triggers. | | `create_time` | timestamp | OUTPUT_ONLY | When the trigger was created | | `update_time` | timestamp | OUTPUT_ONLY | When the trigger was last modified | | `delete_time` | timestamp | OUTPUT_ONLY | When the trigger was soft-deleted (null if active) | **Example** ```json { "name": "triggers/daily-health-check", "displayName": "Daily Health Check", "description": "Runs a health check every morning at 9 AM Eastern", "agent": "agents/health-checker", "configuration": { "cron": { "schedule": "0 9 * * *", "timezone": "America/New_York" } }, "enabled": true, "createTime": "2026-02-06T01:42:31.481530Z", "updateTime": "2026-02-06T01:42:31.481530Z" } ``` ## Trigger Configuration Exactly one of the following fields must be set to determine the trigger type. | Field | Type | Description | |:------|:-----|:------------| | `cron` | [CronTriggerConfig](#cron-trigger-config) | Trigger fires on the cron schedule | | `manual` | [ManualTriggerConfig](#manual-trigger-config) | Trigger can only be manually invoked via InvokeTrigger | | `post_deploy` | [PostDeployTriggerConfig](#post-deploy-trigger-config) | Trigger fires once after a specific commit deploys | ## Cron Trigger Config | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `schedule` | string | Yes | Standard 5-field cron expression (e.g. `"0 9 * * *"` for daily at 9 AM, `"*/15 * * * *"` for every 15 minutes) | | `timezone` | string | No | IANA timezone for interpreting the schedule (e.g. `"America/New_York"`). Defaults to `"UTC"`. | ## Manual Trigger Config Empty object. Manual triggers have no automatic execution and can only be invoked via InvokeTrigger. ## Post Deploy Trigger Config | Field | Type | Required | Description | |:------|:-----|:---------|:------------| | `repository` | string | Yes | GitHub repository in `"owner/repo"` format | | `environment` | string | Yes | Environment label to watch (e.g. `"production"`, `"staging"`) | | `sha` | string | Yes | Commit SHA that must deploy before this trigger fires. Also fires for descendant commits. Immutable after creation. | | `delay` | duration | Yes | How long to wait after the deployment before firing (e.g. `"300s"` for 5 minutes) | ## Trigger Activation State Output-only state set by the system when a matching deployment is detected. Only post_deploy triggers have this set. | Field | Type | Description | |:------|:-----|:------------| | `post_deploy` | [PostDeployActivationState](#post-deploy-activation-state) | Activation state for post-deploy triggers | ## Post Deploy Activation State | Field | Type | Description | |:------|:-----|:------------| | `deployment` | string | The deployment that triggered activation (`deployments/{id}`) | | `deployed_sha` | string | The SHA that was actually deployed (may be a descendant of the configured SHA) | | `deploy_time` | timestamp | Time of the deployment | | `fire_at_time` | timestamp | Precomputed time to fire (`deploy_time` + `delay`) | | `fired_time` | timestamp | When a session was created, or null if activated but not yet fired | ### Activity Activities represent individual events in an agent session's conversation history. An Activity is a union type -- exactly one of the following payload fields will be set. | Field | Type | Description | |:------|:-----|:------------| | `user` | [UserActivity](#user-activity) | A message or action from a non-LLM actor (human user, system, or tool results) | | `assistant` | [AssistantActivity](#assistant-activity) | A message or action generated by the LLM | | `error` | [Error](#error) | An error that occurred during execution | | `compaction` | [Compaction](#compaction) | A summarization of earlier conversation history | | `slack_thread` | [SlackThreadActivity](#slack-thread-activity) | A reply in a Slack thread the agent is participating in | | `slack_mention` | [SlackMentionActivity](#slack-mention-activity) | An @-mention of the agent in Slack | | `slack_reaction` | [SlackReactionActivity](#slack-reaction-activity) | An emoji reaction added to an agent-sent message in Slack | | `external_agent` | [ExternalAgentActivity](#external-agent-activity) | A message from another agent | | `timestamp` | timestamp | When this activity occurred | ## User Activity A message or action from a non-LLM actor. | Field | Type | Description | |:------|:-----|:------------| | `text` | [Text](#text) | Text content of the user message | | `tool_results` | [ToolResult](#tool-result)[] | Results from tool calls the user (or system) executed | | `author` | string | Author identifier | ## Assistant Activity A message or action generated by the LLM. | Field | Type | Description | |:------|:-----|:------------| | `text` | [Text](#text) | Generated text content | | `tool_calls` | [ToolCall](#tool-call)[] | Tool calls the assistant wants to execute | ## Slack Thread Activity A reply posted to a Slack thread the agent is participating in. | Field | Type | Description | |:------|:-----|:------------| | `permalink` | string | Full Slack URL to the thread | | `user_id` | string | Slack user ID of the person who replied | | `text` | string | Reply content | | `channel_name` | string | Name of the Slack channel | ## Slack Mention Activity An @Firetiger mention in a Slack message. | Field | Type | Description | |:------|:-----|:------------| | `permalink` | string | Slack URL to the mention | | `user_id` | string | Slack user ID of the person who mentioned the agent | | `text` | string | Message text (with @mention stripped) | | `channel_id` | string | Slack channel ID | | `channel_name` | string | Name of the Slack channel | | `thread_ts` | string | Thread timestamp | | `message_ts` | string | Message timestamp | ## Slack Reaction Activity An emoji reaction added to an agent-sent message in Slack. Used to capture user feedback on agent responses. | Field | Type | Description | |:------|:-----|:------------| | `permalink` | string | Slack URL to the reacted message | | `user_id` | string | Slack user ID of the person who added the reaction | | `reaction` | string | Emoji name without colons (e.g., "thumbsup", "+1", "white_check_mark") | | `channel_id` | string | Slack channel ID | | `channel_name` | string | Name of the Slack channel | | `message_ts` | string | Timestamp of the message that was reacted to | | `thread_ts` | string | Thread timestamp if the reacted message is in a thread | ## External Agent Activity A message from another agent session. | Field | Type | Description | |:------|:-----|:------------| | `source_session` | string | Resource name of the source agent session | | `source_agent_name` | string | Human-readable name of the source agent | | `title` | string | Message title | | `summary` | string | Brief summary | | `content` | string | Full content (markdown supported) | ## Compaction A summarization that replaces earlier conversation history to keep sessions manageable. | Field | Type | Description | |:------|:-----|:------------| | `summary` | string | Summary of the preceding messages that were compacted | | `truncated_token_count` | integer | Number of tokens that were truncated | ## Text | Field | Type | Description | |:------|:-----|:------------| | `text` | string | The text content | ## Tool Call A request from the assistant to invoke a tool. | Field | Type | Description | |:------|:-----|:------------| | `id` | string | Unique identifier for this tool call (referenced by the corresponding ToolResult) | | `name` | string | Name of the tool to invoke (e.g. `TOOL_POSTGRES_QUERY`) | | `arguments` | string | JSON-encoded arguments for the tool | ## Tool Result The result of executing a tool call. | Field | Type | Description | |:------|:-----|:------------| | `tool_call_id` | string | ID of the ToolCall this result corresponds to | | `content` | string | Output of the tool execution | | `is_error` | boolean | Whether the tool execution failed | ## Error An error that occurred during session execution. | Field | Type | Description | |:------|:-----|:------------| | `message` | string | Human-readable error message |