---
title: "Get started with foundryR"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Get started with foundryR}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
fixture_dir <- "getting-started"
recording <- nzchar(Sys.getenv("FOUNDRY_RECORD_DOCS"))
have_fixtures <- dir.exists(fixture_dir) && length(list.files(fixture_dir)) > 0
run_api <- requireNamespace("httptest2", quietly = TRUE) &&
  (recording || have_fixtures)
library(foundryR)
if (run_api) {
  httptest2::start_vignette(fixture_dir)
}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = run_api,
  fig.width = 7, fig.height = 4.5, out.width = "100%")
```

Work through this article once before the task-specific ones. It sets up credentials, gets one response, extracts two fields from course comments, and compares three short texts by embedding. Calls to Azure show output recorded from a live run, and setup code is shown but not run.

## Install

Install the released package from CRAN:

```{r install-cran, eval = FALSE}
install.packages("foundryR")
```

The development version on GitHub has the newest fixes.

```{r install-github, eval = FALSE}
# install.packages("pak")
pak::pak("farach/foundryR")
```

## Configure credentials

For API-key authentication, store the resource endpoint and key once:

```{r config-key, eval = FALSE}
library(foundryR)
foundry_set_endpoint(Sys.getenv("AZURE_FOUNDRY_ENDPOINT"), store = TRUE)
foundry_set_key("your-api-key", store = TRUE)
```

`store = TRUE` writes package settings under `tools::R_user_dir("foundryR", "config")`; the file is plain text, so use session-only credentials or a refreshable token provider when that fits your security policy.

Microsoft Entra ID uses a token provider instead of a static key.

```{r config-entra, eval = FALSE}
foundry_set_endpoint(Sys.getenv("AZURE_FOUNDRY_ENDPOINT"), store = TRUE)
foundry_set_token_provider(foundry_token_azure_cli(), scope = "resource")
foundry_set_token_provider(foundry_token_azure_cli("https://ai.azure.com"), scope = "project")
```

The resource token uses the Cognitive Services audience. The project token uses the `https://ai.azure.com` audience. A provider is a function that asks the Azure CLI for a fresh token when the cached one is about to expire, so it lasts for the R session rather than being stored; put the two provider lines in your project's `.Rprofile` if you want them every session.

`foundry_check_setup()` confirms that the resource endpoint, credentials, and default deployment work.

```{r check-setup, eval = FALSE}
foundry_check_setup()
```

## Understand endpoints and routes

Microsoft Foundry exposes two endpoint shapes. A resource endpoint looks like `https://<resource>.openai.azure.com`. It is the default route for Responses API calls, files, vector stores, and most evaluation workflows that use OpenAI graders on existing columns. A project endpoint looks like `https://<resource>.services.ai.azure.com/api/projects/<project>`. You need it for conversations, server-side agents, agent-backed responses, Foundry built-in evaluators, model-target evaluations, agent evaluations, and stored-response evaluations.

Set a project endpoint when your workflow needs project objects:

```{r config-project, eval = FALSE}
foundry_set_project_endpoint(Sys.getenv("AZURE_FOUNDRY_PROJECT_ENDPOINT"), store = TRUE)
```

Conversations, agents, and the evaluations that need the project use it automatically. Responses, files, vector stores, and other evaluations stay on the resource endpoint unless you pass `project_endpoint =` on a call, or call `foundry_set_route("project")` to send them to the project for the rest of the R session.

Project evaluations need a Microsoft Entra ID token. In live tests on the default project, responses, conversations, files, vector stores, and agents all accepted the resource API key.

## Know deployment names

The `model =` argument takes a deployment name, not a base model name. For example, if you deploy base model `gpt-5-nano` with deployment name `course-coder`, call:

```{r deployment-name, eval = FALSE}
foundry_response("Code this comment.", model = "course-coder")
```

`foundry_models()` lists models available to the resource. It does not list the deployments you created in the Foundry portal.

```{r list-models, eval = FALSE}
models <- foundry_models()
models[, c("id", "owned_by")]
```

## Get a first response

The Responses API returns a tibble. Print the answer column when you want the text a reader or analyst will see:

```{r first-response}
response <- foundry_response("Answer in one sentence: what is R?")

response$output_text
```

Token columns support cost checks and audit logs.

```{r first-response-tokens}
response[, c(
  "input_tokens",
  "output_tokens",
  "reasoning_tokens",
  "cached_input_tokens",
  "total_tokens"
)]
```

`gpt-5-nano` is a reasoning model. Hidden reasoning tokens are included in `output_tokens`, so they are part of the output-token cost even though they are not visible in `output_text`.

## Extract structured fields

Use structured extraction when free text needs to become analysis columns. This small schema codes course comments into sentiment and one short issue label:

```{r first-extract}
schema <- foundry_schema(
  sentiment = schema_enum(c("positive", "negative", "mixed")),
  issue = schema_string("A short label for what the comment is about.")
)

comments <- c(
  "The lecture made regression much clearer.",
  "The homework instructions were hard to follow.",
  "The examples helped, but I wanted more time for practice."
)

coded <- foundry_extract(comments, schema = schema)
coded[, c("sentiment", "issue")]
```

The enum keeps `sentiment` to three values you can count. The free-text `issue` field comes back in whatever form the model chooses, so two runs, or two similar comments, can produce labels that do not match. When a field needs to be counted, give it an enum and a codebook, as in `vignette("annotation-workflow")`.

The returned tibble also contains dot-prefixed metadata such as response IDs, status, and raw response payloads. Keep those columns when you need provenance. Check `.error` before you analyze the fields. A failed row has missing fields, and `.error_msg` says why it failed.

## Embed and compare text

Embeddings turn text into numeric vectors. For a first check, inspect the dimensions and ask which pair is most similar:

```{r first-embed}
texts <- c(
  "The lecture made regression much clearer.",
  "Regression finally made sense after this class.",
  "The homework instructions were hard to follow."
)

embeddings <- foundry_embed(texts, model = "text-embedding-3-small")
embeddings[, c("text", "n_dims")]

foundry_similarity(embeddings, top_k = 1)
```

`text-embedding-3-small` returns 1536 dimensions. `foundry_similarity()` computes cosine similarity from the embedding list-column.

## Choose the next article

| Task | Read next |
| --- | --- |
| Learn the main workflow | [From text to defensible estimates](annotation-workflow.html) |
| Annotate many rows | [Annotate at scale with the Batch API](files-batches.html) |
| Search, cluster, or compare text | [Embeddings for research](embeddings.html) |
| Put embeddings in a model recipe | [Embeddings in tidymodels recipes](tidymodels.html) |
| Evaluate models or agents in Foundry | [Evaluate models and agents in Microsoft Foundry](evaluations.html) |
| Analyze evaluation results | [Analyze evaluation results with uncertainty](evaluation-analysis.html) |
| Gate outputs for safety | [Content Safety gates in a research pipeline](content-safety.html) |
| Use tools, web search, or stateful turns | [Responses API](responses-api.html) |
| Check endpoint and authentication coverage | [API support matrix](api-support.html) |
| Transcribe or translate audio | [Transcribe and translate audio](audio.html) |
| Generate images | [Generate images](media-generation.html) |

```{r cleanup, include = FALSE}
if (run_api) {
  httptest2::end_vignette()
}
```
