Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Publish Python Package

on:
workflow_dispatch:
release:
types: [published]

permissions:
contents: read

jobs:
release-build:
runs-on: ubuntu-latest
# PyPI use trusted publisher
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install uv
uv venv
make dev
- name: Build
run: |
make build
- name: Validate
run: |
WHEEL=$(ls dist/*.whl | head -n 1)
python -m pip install "${WHEEL}"
python -c "from oci_genai_auth import OciSessionAuth; from oci_genai_auth import OciUserPrincipalAuth; import oci_genai_auth;"
# - name: Publish to Test PyPI
# run: |
# python -m pip install twine
# twine check dist/*
# twine upload --verbose -r testpypi dist/*
- name: Publish to PyPI
run: |
python -m pip install twine
twine check dist/*
twine upload --verbose dist/*
39 changes: 39 additions & 0 deletions .github/workflows/run-all-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Unit test, format and lint check

on:
workflow_dispatch:
pull_request:
branches: [ "main" ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install uv
uv venv
make dev
- name: Format and Lint
run: |
make check
- name: Test with pytest
run: |
make test
- name: Build
run: |
make build
87 changes: 87 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Mac
.DS_Store

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class


# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST


# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/

# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
.idea/
*.iml

# Visual Studio Code
.vscode/

# Ruff stuff:
.ruff_cache/

# PyPI configuration file
.pypirc

# Demo folder
.demo
2 changes: 0 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
*Detailed instructions on how to contribute to the project, if applicable. Must include section about Oracle Contributor Agreement with link and instructions*

# Contributing to this repository

We welcome your contributions! There are multiple ways to contribute.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2026 Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.

The Universal Permissive License (UPL), Version 1.0

Expand Down
69 changes: 69 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Define the directory containing the source code
SRC_DIR := ./src
TEST_DIR := ./tests
EXAMPLE_DIR := ./examples

# Optional install extras via `make install <extra>` or `make build <extra>`
ifneq (,$(filter install build,$(MAKECMDGOALS)))
EXTRAS := $(filter-out install build,$(MAKECMDGOALS))
comma := ,
empty :=
space := $(empty) $(empty)
EXTRA_LIST := $(subst $(space),$(comma),$(strip $(EXTRAS)))
endif

.PHONY: all
all: test lint build

##@ General

.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-24s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

.PHONY: install
install: ## Install project dependencies. Example: `make install openai`
ifneq ($(strip $(EXTRA_LIST)),)
uv pip install --editable ".[${EXTRA_LIST}]"
else
uv pip install --editable .
endif

ifneq ($(strip $(EXTRAS)),)
.PHONY: $(EXTRAS)
$(EXTRAS):
@:
endif

.PHONY: dev
dev: ## Install development dependencies.
uv pip install ".[dev]"

.PHONY: test
test: ## Run tests.
uv run --no-project --no-reinstall pytest $(TEST_DIR) --cov --cov-config=.coveragerc -vv -s

.PHONY: clean
clean: ## Remove build artifacts.
rm -rf build dist *.egg-info .pytest_cache .coverage

.PHONY: format
format: ## Format code using ruff.
uv run --no-project --no-reinstall isort $(SRC_DIR) $(TEST_DIR) $(EXAMPLE_DIR)
uv run --no-project --no-reinstall ruff format $(SRC_DIR) $(TEST_DIR) $(EXAMPLE_DIR); uv run --no-project --no-reinstall ruff check --fix $(SRC_DIR) $(TEST_DIR) $(EXAMPLE_DIR)

.PHONY: lint
lint: ## Run linters using ruff.
uv run --no-project --no-reinstall ruff format --diff $(SRC_DIR) $(TEST_DIR)
uv run --no-project --no-reinstall mypy $(SRC_DIR) $(TEST_DIR)

.PHONY: check
check: format lint ## Run format and lint.

##@ Build

.PHONY: build
build: ## Build the application.
uv build
121 changes: 97 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,117 @@
*This repository acts as a template for all of Oracle’s GitHub repositories. It contains information about the guidelines for those repositories. All files and sections contained in this template are mandatory, and a GitHub app ensures alignment with these guidelines. To get started with a new repository, replace the italic paragraphs with the respective text for your project.*
# oci-genai-auth

# Project name
[![PyPI - Version](https://img.shields.io/pypi/v/oci-genai-auth.svg)](https://pypi.org/project/oci-genai-auth)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/oci-genai-auth.svg)](https://pypi.org/project/oci-genai-auth)

*Describe your project's features, functionality and target audience*
The **OCI GenAI Auth** Python library provides OCI request-signing helpers for the OpenAI-compatible REST APIs hosted by OCI Generative AI. Partner/Passthrough endpoints do not store conversation history on OCI servers, while AgentHub (non-passthrough) stores data on OCI-managed servers.

## Installation
## Table of Contents

*Provide detailed step-by-step installation instructions. You can name this section **How to Run** or **Getting Started** instead of **Installation** if that's more acceptable for your project*
- [Before you start](#before-you-start)
- [Using OCI IAM Auth](#using-oci-iam-auth)
- [Using API Key Auth](#using-api-key-auth)
- [Using AgentHub APIs (non-passthrough)](#using-agenthub-apis-non-passthrough)
- [Using Partner APIs (passthrough)](#using-partner-apis-passthrough)
- [Running the Examples](#running-the-examples)

## Documentation
## Before you start

*Developer-oriented documentation can be published on GitHub, but all product documentation must be published on <https://docs.oracle.com>*
**Important!**

## Examples
Note that this package, as well as API keys package described below, only supports OpenAI, xAi Grok and Meta LLama models on OCI Generative AI.

*Describe any included examples or provide a link to a demo/tutorial*
Before you start using this package, determine if this is the right option for you.

## Help
If you are looking for a seamless way to port your code from an OpenAI compatible endpoint to OCI Generative AI endpoint, and you are currently using OpenAI-style API keys, you might want to use [OCI Generative AI API Keys](https://docs.oracle.com/en-us/iaas/Content/generative-ai/api-keys.htm) instead.

*Inform users on where to get help or how to receive official support from Oracle (if applicable)*
With OCI Generative AI API Keys, use the native `openai` SDK like before. Just update the `base_url`, create API keys in your OCI console, insure the policy granting the key access to generative AI services is present and you are good to go.

## Contributing
- Create an API key in Console: **Generative AI** -> **API Keys**
- Create a security policy: **Identity & Security** -> **Policies**

*If your project has specific contribution requirements, update the CONTRIBUTING.md file to ensure those requirements are clearly explained*
To authorize a specific API Key
```
allow any-user to use generative-ai-family in compartment <compartment-name> where ALL { request.principal.type='generativeaiapikey', request.principal.id='ocid1.generativeaiapikey.oc1.us-chicago-1....' }
```

This project welcomes contributions from the community. Before submitting a pull request, please [review our contribution guide](./CONTRIBUTING.md)
To authorize any API Key
```
allow any-user to use generative-ai-family in compartment <compartment-name> where ALL { request.principal.type='generativeaiapikey' }
```

## Security
## Using OCI IAM Auth

Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process
Use OCI IAM auth when you want to sign requests with your OCI profile (session/user/resource/instance principal) instead of API keys.

## License
```python
import httpx
from openai import OpenAI
from oci_genai_auth import OciSessionAuth

*The correct copyright notice format for both documentation and software is*
"Copyright (c) [year,] year Oracle and/or its affiliates."
*You must include the year the content was first released (on any platform) and the most recent year in which it was revised*
client = OpenAI(
base_url="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/openai/v1",
api_key="not-used",
http_client=httpx.Client(auth=OciSessionAuth(profile_name="DEFAULT")),
)
```

Copyright (c) 2026 Oracle and/or its affiliates.
## Using API Key Auth

*Replace this statement if your project is not licensed under the UPL*
Use OCI Generative AI API Keys if you want a direct API-key workflow with the OpenAI SDK.

Released under the Universal Permissive License v1.0 as shown at
<https://oss.oracle.com/licenses/upl/>.
```python
import os
from openai import OpenAI

client = OpenAI(
base_url="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/openai/v1",
api_key=os.getenv("OPENAI_API_KEY"),
)
```

## Using AgentHub APIs (non-passthrough)

AgentHub runs in non-pass-through mode and provides a unified interface for interacting with models and agentic capabilities.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can provide an updated verison here

It is compatible with OpenAI's Responses API and the Open Responses Spec, enabling developers/users to: build agents with OpenAI SDK.
Only the project OCID is required.

```python
import httpx
from openai import OpenAI
from oci_genai_auth import OciSessionAuth

client = OpenAI(
base_url="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/openai/v1",
api_key="not-used",
project="ocid1.generativeaiproject.oc1.us-chicago-1.aaaaaaaaexample",
http_client=httpx.Client(auth=OciSessionAuth(profile_name="DEFAULT")),
)
```

## Using Partner APIs (passthrough)

Partner endpoints run in pass-through mode and require the compartment OCID header.

```python
import httpx
from openai import OpenAI
from oci_genai_auth import OciSessionAuth

client = OpenAI(
base_url="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/v1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/v1" here.

"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/v1" should not even exist for partner api and let's not promote it further in docs

api_key="not-used",
default_headers={
"opc-compartment-id": "ocid1.compartment.oc1..aaaaaaaaexample",
},
http_client=httpx.Client(auth=OciSessionAuth(profile_name="DEFAULT")),
)
```


## Running the Examples

1. Update `examples/agenthub/openai/common.py` and/or `examples/partner/openai/common.py` with your `COMPARTMENT_ID`, `PROJECT_OCID`, and set the correct `REGION`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create respective README.md in examples/agenthub/README.md and examples/partner/openai/README.md

2. Set the `OPENAI_API_KEY` environment variable when an example uses API key authentication.
3. Install optional dev dependencies: `pip install -e '.[dev]'`.

Run an example either by calling its `main()` method or from the command line.
Loading
Loading