# kcode-openai-api Agent Integration Reference
`kcode-openai-api` is a standalone asynchronous Rust 2024 library for the
direct OpenAI API features Kennedy uses. It owns fixed OpenAI transport,
request validation, response normalization, and API-key lifetime. The
integrating server owns HTTP routes, authentication, authorization, secret
retrieval, application request limits, logging, cancellation, persistence,
deployment, and spending policy.
The Cargo package is `kcode-openai-api`; its Rust crate path is
`kcode_openai_api`.
Kennedy's ordinary text generation is intentionally absent. It runs through a
separately authenticated Codex path and does not use this library's OpenAI API
key.
## Open a client
```rust,no_run
use kcode_openai_api::{OpenAi, Result};
fn open(api_key: String) -> Result<OpenAi> {
OpenAi::open(api_key)
}
```
`OpenAi::open` validates and takes ownership of the API key. The trimmed key is
zeroized on final drop, redacted from `Debug`, placed in a sensitive HTTP
header, and sent only as a bearer credential. It is never placed in a URL,
request body, returned value, or error. The client disables environment proxy
discovery, redirects, automatic retries, and referrers; permits HTTPS only; and
uses a five-minute request timeout.
Clones share the key and HTTP connection pool. The crate has no credential
discovery, database, filesystem storage, recovery mode, or persisted state.
## Audio transcription
```rust,no_run
use kcode_openai_api::{AudioInput, OpenAi, Result, TranscriptionRequest};
async fn transcribe(openai: &OpenAi, webm: Vec<u8>) -> Result<String> {
let audio = AudioInput::new("voice-note.webm", "audio/webm", webm)?;
let result = openai
.transcribe(TranscriptionRequest::new(audio))
.await?;
Ok(result.text)
}
```
`TranscriptionRequest::new` uses `gpt-4o-transcribe`, JSON output, and
Kennedy's faithful-transcription prompt. Callers may replace or remove the
prompt and may provide a lowercase ISO-639-1 language code.
The recording remains in memory and is uploaded once as multipart form data.
It must be non-empty, at most 25 MiB, have a safe basename, use a supported
FLAC, MP3, MP4, MPEG, MPGA, M4A, OGG, WAV, or WebM extension, and carry a
corresponding supported audio or video MIME type.
The normalized `Transcription` contains non-empty text, optional typed
token-or-duration usage, and the provider request ID when available.
This method is batch transcription only. Streaming, diarization, timestamps,
speaker reference samples, translations, and arbitrary transcription-model
selection are outside the library.
## Prompt-driven image analysis
```rust,no_run
use kcode_openai_api::{
ImageAnalysisRequest, ImageDetail, ImageInput, ImageMediaType, OpenAi,
Result,
};
async fn analyze(openai: &OpenAi, png: Vec<u8>) -> Result<String> {
let image = ImageInput::new(ImageMediaType::Png, png)?;
let mut request = ImageAnalysisRequest::new(
image,
"Identify the important objects and explain what is happening.",
);
request.detail = ImageDetail::High;
let result = openai.analyze_image(request).await?;
Ok(result.text)
}
```
`analyze_image` sends one non-streaming `POST /v1/responses` request using the
fixed `gpt-5.6` model. It pairs one caller-owned in-memory image with the exact
prompt supplied by the caller. The operation explicitly sets `store:false` and
does not send tools, files, URLs, conversation state, or an output-token cap.
`ImageInput` accepts declared PNG, JPEG, WebP, or GIF media and non-empty image
bytes up to 20 MiB. The library uses the declared media type to construct an
in-memory Base64 data URL; it does not inspect, transform, persist, or fetch the
image. `ImageInput::Debug` reports only the media type and byte count.
The prompt must contain 1 through 32,000 characters after trim validation. Its
original contents, including surrounding whitespace, are preserved in the
request. `ImageDetail` supports `Auto`, `Low`, `High`, and `Original`, with
`Auto` as the default.
The normalized `ImageAnalysis` contains:
- ordered, non-empty assistant output text;
- the OpenAI response ID;
- the model identifier returned by OpenAI;
- `Completed` or `Incomplete` status, including an optional incomplete reason;
- optional typed token usage, including reported cached-input,
cache-write-input, and reasoning-output details; and
- the provider request ID when available.
Only assistant `output_text` content is joined into the returned text.
Reasoning records, refusals, and other output item types are not returned as
analysis text. An incomplete response is accepted only when it still contains
non-empty assistant text.
The operation does not provide caption-specific semantics, image annotation,
coordinates, masks, segmentation, multiple images, remote image URLs, Files
API integration, streaming, tools, stateful conversations, or arbitrary model
selection. The caller controls the requested analysis through the prompt.
## Image generation
```rust,no_run
use kcode_openai_api::{
ImageFormat, ImageGenerationRequest, ImageQuality, ImageSize, OpenAi,
Result,
};
async fn generate(openai: &OpenAi) -> Result<Vec<u8>> {
let mut request = ImageGenerationRequest::new(
"A clean editorial illustration of a radio telescope at dusk",
);
request.size = ImageSize::dimensions(1536, 1024)?;
request.quality = ImageQuality::High;
request.output_format = ImageFormat::WebP;
request.output_compression = Some(90);
let result = openai.generate_image(request).await?;
Ok(result.image.data)
}
```
`generate_image` sends one non-streaming
`POST /v1/images/generations` request using `gpt-image-2` and requests exactly
one image. It returns decoded bytes in memory, the actual or fallback output
format, optional selected size and quality metadata, optional typed token
usage, creation time, and the provider request ID.
Defaults are automatic size, automatic quality, PNG output, automatic opaque
background selection, standard automatic moderation, and no explicit
compression. JPEG and WebP accept compression from 0 through 100. GPT Image 2
does not support transparent output, so the public background enum exposes only
automatic and opaque behavior.
Explicit dimensions must use 16-pixel increments, keep each edge at or below
3,840 pixels, stay within a 3:1 aspect ratio, and contain 655,360 through
8,294,400 total pixels. The prompt must contain 1 through 32,000 characters.
The optional `user` value is forwarded to OpenAI's abuse-monitoring field; the
integrating server should use a stable, privacy-preserving identifier rather
than personal data.
This surface does not include image edits, reference images, multiple outputs,
streaming partial images, or arbitrary image-model selection.
## Errors and data handling
Local validation fails before network access. Transport errors are reduced to
timeout or service-reachability classes. Provider failures retain only the HTTP
status, a bounded control-cleaned provider code and message, and the request ID.
Complete provider error bodies are not returned. Successful and error response
bodies are bounded to 128 MiB.
No automatic retries are performed because a billable operation may have
completed before a timeout or connection failure becomes visible locally. The
integrating application may make a policy-aware retry after considering the
operation, error class, and provider request ID.
The crate never writes credentials, audio, images, prompts, transcripts,
analysis text, generated images, or usage to disk. Returned byte and text
values are ordinary owned Rust values; their later storage, logging, and
lifetime are caller responsibilities.
## Managed-library maintenance
The literal root package version in `Cargo.toml` is canonical. No parallel
version file is required. All maintained files are ordinary UTF-8 text. Keep
`target/`, credentials, source media, generated media, and other binary output
outside the managed library.
The standard managed-library check performs dependency fetch, formatting,
build, Clippy with warnings denied, tests, and documentation tests.