Metadata-Version: 2.4
Name: marona
Version: 0.6.1
Summary: Provider-neutral AI runtime and MCP/Skill gateway for Hub connections, managed responses, and external agents.
Author: Blessing Nyuwani
License-Expression: MIT
Project-URL: Homepage, https://www.marona.ai
Project-URL: Documentation, https://hub.marona.ai
Keywords: marona,sdk,mcp,agents,ai,runtime
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1.0,>=0.28
Provides-Extra: dev
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
Requires-Dist: build<2.0,>=1.2; extra == "dev"
Requires-Dist: twine<7.0,>=6.0; extra == "dev"
Dynamic: license-file

# Marona Python SDK

Provider-neutral AI runtime and MCP/Skill gateway for Marona Hub connections,
managed responses, and bring-your-own-agent integrations.

```bash
pip install marona
```

## 1. Marona Hub

Connect Apps and governed Skills as one neutral MCP tool collection.

```python
from marona import Marona

marona = Marona(api_key="YOUR_MARONA_API_KEY")

connection = marona.hub.connect(
    apps=["sda-books"],
    skills=["download-book"],
)

tools = connection.list_tools()
result = connection.call_tool(
    "skill__download_book",
    {"request": "Download Steps to Christ"},
)
```

`MCPConnection` is not tied to OpenAI, LangGraph, CrewAI, or another model
vendor. It exposes:

```python
connection.list_tools()
connection.call_tool(name, arguments)
connection.server_url
connection.server_urls
connection.session
```

Marona Hub owns discovery, identity, permissions, App and Skill resolution,
approvals, governed execution, and online, offline, or hybrid availability.

Use the asynchronous methods inside an event loop:

```python
connection = await marona.hub.connect_async(
    apps=["sda-books"],
    skills=["download-book"],
)
tools = await connection.list_tools_async()
result = await connection.call_tool_async(
    "skill__download_book",
    {"request": "Download Steps to Christ"},
)
```

## 2. Marona Runtime

Use `responses.create(...)` when Marona should manage model reasoning, tool
selection, permission and approval checks, execution, and the final response.

```python
from marona import Marona

marona = Marona(api_key="YOUR_MARONA_API_KEY")

tools = marona.hub.connect(
    apps=["sda-books"],
    skills=["download-book"],
)

response = marona.responses.create(
    model="gpt-5.6",
    tools=tools,
    input="Download Steps to Christ",
)

print(response.output_text)
```

The same request supports managed, direct-provider, private, and local models:

```python
model="gpt-5.6"                    # Marona-managed model
model="openai/gpt-5.6"
model="anthropic/claude-sonnet"
model="google/gemini"
model="ollama/qwen3"
model="litellm/local-qwen"
model="local/qwen"
```

Register only custom providers or downloaded in-process models:

```python
marona.models.register(
    name="office/company-assistant",
    endpoint="https://models.office.example/v1",
    model="company-assistant-v2",
    api_key="YOUR_PROVIDER_KEY",
)

marona.models.register(
    name="local/qwen",
    executor=qwen_executor,
    context_window=8192,
    max_output_tokens=512,
)
```

For asynchronous applications, call `await marona.responses.create_async(...)`.

### Images And Documents

```python
response = marona.responses.create(
    model="openai/gpt-5.6",
    input=[
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "Summarize this document and image."},
                {"type": "input_image", "image_url": "https://example.com/image.jpg"},
                {
                    "type": "input_file",
                    "filename": "report.pdf",
                    "file_data": "data:application/pdf;base64,...",
                    "detail": "high",
                },
            ],
        }
    ],
)
```

## 3. Bring Your Own Agent

The external framework owns its Agent, reasoning, and orchestration. Marona
supplies neutral MCP tools and retains authorization, approvals, and execution.

### OpenAI Agents SDK Example

```python
from marona import Marona
from agents import Agent, Runner

marona = Marona(api_key="YOUR_MARONA_API_KEY")
connection = marona.hub.connect(
    apps=["sda-books"],
    skills=["download-book"],
)

# Adapt only at the framework boundary. Marona itself remains vendor-neutral.
framework_tools = your_openai_agents_mcp_adapter(connection)

agent = Agent(
    name="Book Assistant",
    model="gpt-5.6",
    instructions="Help users find and download books.",
    tools=framework_tools,
)

result = Runner.run_sync(agent, "Download Steps to Christ")
print(result.final_output)
```

`your_openai_agents_mcp_adapter(...)` represents the OpenAI-specific adapter at
the framework boundary; it is not part of Marona's vendor-neutral core API.

An MCP-compatible framework can map its standard tool-list and tool-call hooks
directly to `connection.list_tools()` and `connection.call_tool(...)`. Marona
does not claim that one Python tool object automatically satisfies every agent
framework's proprietary interface.

## Execution Modes

Set mode when creating Marona:

```python
marona = Marona(
    api_key="YOUR_MARONA_API_KEY",
    mode="hybrid",
)
```

- `online`: network models and online MCP targets are allowed.
- `hybrid`: local/private execution may fall back to online execution.
- `offline`: only installed local Apps, Skills, data, and local models run.

Changing `model` never changes App, Skill, permission, approval, or MCP rules.
