mirror of https://github.com/kortix-ai/suna.git
Add README and update API URL in Kortix class
- Introduced a new README.md file for the Kortix SDK, detailing installation instructions, quick start examples, and environment setup. - Updated the default API URL in the Kortix class constructor from `http://localhost:8000/api` to `https://suna.so/api`, ensuring consistency with the production environment.
This commit is contained in:
parent
c94a0becd9
commit
403561f823
|
@ -0,0 +1 @@
|
|||
.kvstore.json
|
|
@ -0,0 +1,72 @@
|
|||
# Kortix SDK
|
||||
|
||||
[](https://python.org)
|
||||
|
||||
A Python SDK that enables you to create, manage, and interact with AI agents on [Suna](https://suna.so).
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
Install directly from the GitHub repository:
|
||||
|
||||
```bash
|
||||
pip install "kortix @ git+https://github.com/kortix/suna.git@main#subdirectory=sdk"
|
||||
```
|
||||
|
||||
Or using uv:
|
||||
|
||||
```bash
|
||||
uv add "kortix @ git+https://github.com/kortix/suna.git@main#subdirectory=sdk"
|
||||
```
|
||||
|
||||
## 🔧 Quick Start
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from kortix import kortix
|
||||
|
||||
async def main():
|
||||
mcp_tools = kortix.MCPTools(
|
||||
"http://localhost:4000/mcp/", # Point to any HTTP MCP server
|
||||
"Kortix",
|
||||
)
|
||||
await mcp_tools.initialize()
|
||||
|
||||
# Initialize the client
|
||||
client = kortix.Kortix(api_key="your-api-key")
|
||||
|
||||
# Create an agent
|
||||
agent = await client.Agent.create(
|
||||
name="My Assistant",
|
||||
system_prompt="You are a helpful AI assistant.",
|
||||
mcp_tools=[mcp_tools],
|
||||
allowed_tools=["get_wind_direction"],
|
||||
)
|
||||
|
||||
# Create a conversation thread
|
||||
thread = await client.Thread.create()
|
||||
|
||||
# Run the agent
|
||||
run = await agent.run("Hello, how are you?", thread)
|
||||
|
||||
# Stream the response
|
||||
stream = await run.get_stream()
|
||||
async for chunk in stream:
|
||||
print(chunk, end="")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## 🔑 Environment Setup
|
||||
|
||||
Get your API key from [https://suna.so/settings/api-keys](https://suna.so/settings/api-keys)
|
||||
|
||||
## 🧪 Running Examples
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
uv sync
|
||||
|
||||
# Run the main example
|
||||
PYTHONPATH=$(pwd) uv run example/example.py
|
||||
```
|
|
@ -0,0 +1,69 @@
|
|||
# Run with `PYTHONPATH=$(pwd) uv run example/example.py`
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from kortix import kortix
|
||||
from kortix.utils import print_stream
|
||||
|
||||
|
||||
from .kv import kv
|
||||
from .mcp_server import mcp
|
||||
|
||||
|
||||
async def main():
|
||||
"""
|
||||
Please ignore the asyncio.exceptions.CancelledError that is thrown when the MCP server is stopped. I couldn't fix it.
|
||||
"""
|
||||
# Start the MCP server in the background
|
||||
asyncio.create_task(
|
||||
mcp.run_http_async(
|
||||
show_banner=False, log_level="error", host="0.0.0.0", port=4000
|
||||
)
|
||||
)
|
||||
|
||||
# Create the MCP tools client with the URL of the MCP server that's accessible by the Suna instance
|
||||
mcp_tools = kortix.MCPTools(
|
||||
"http://localhost:4000/mcp/", # Since we are running Suna locally, we can use the local URL
|
||||
"Kortix",
|
||||
allowed_tools=["get_wind_direction"],
|
||||
)
|
||||
await mcp_tools.initialize()
|
||||
|
||||
kortix_client = kortix.Kortix(
|
||||
os.getenv("KORTIX_API_KEY", "pk_xxx:sk_xxx"),
|
||||
"http://localhost:8000/api",
|
||||
)
|
||||
|
||||
# Setup the agent
|
||||
agent_id = kv.get("agent_id")
|
||||
if not agent_id:
|
||||
agent = await kortix_client.Agent.create(
|
||||
name="Generic Agent",
|
||||
system_prompt="You are a generic agent. You can use the tools provided to you to answer questions.",
|
||||
mcp_tools=[mcp_tools],
|
||||
allowed_tools=["get_weather"],
|
||||
)
|
||||
kv.set("agent_id", agent._agent_id)
|
||||
else:
|
||||
agent = await kortix_client.Agent.get(agent_id)
|
||||
await agent.update(allowed_tools=["get_weather"])
|
||||
|
||||
# Setup the thread
|
||||
thread_id = kv.get("thread_id")
|
||||
if not thread_id:
|
||||
thread = await kortix_client.Thread.create()
|
||||
kv.set("thread_id", thread._thread_id)
|
||||
else:
|
||||
thread = await kortix_client.Thread.get(thread_id)
|
||||
|
||||
# Run the agent
|
||||
agent_run = await agent.run("What is the wind direction in Bangalore?", thread)
|
||||
|
||||
stream = await agent_run.get_stream()
|
||||
|
||||
await print_stream(stream)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,47 @@
|
|||
import json
|
||||
import os
|
||||
from typing import Any, Optional
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv("./.env")
|
||||
|
||||
|
||||
# Local key-value store for storing agent and thread IDs
|
||||
class LocalKVStore:
|
||||
def __init__(self, filename: str = ".kvstore.json"):
|
||||
self.filename = filename
|
||||
self._data = {}
|
||||
self._load()
|
||||
|
||||
def _load(self):
|
||||
if os.path.exists(self.filename):
|
||||
try:
|
||||
with open(self.filename, "r", encoding="utf-8") as f:
|
||||
self._data = json.load(f)
|
||||
except Exception:
|
||||
self._data = {}
|
||||
else:
|
||||
self._data = {}
|
||||
|
||||
def _save(self):
|
||||
with open(self.filename, "w", encoding="utf-8") as f:
|
||||
json.dump(self._data, f, indent=2)
|
||||
|
||||
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
||||
return self._data.get(key, default)
|
||||
|
||||
def set(self, key: str, value: Any):
|
||||
self._data[key] = value
|
||||
self._save()
|
||||
|
||||
def delete(self, key: str):
|
||||
if key in self._data:
|
||||
del self._data[key]
|
||||
self._save()
|
||||
|
||||
def clear(self):
|
||||
self._data = {}
|
||||
self._save()
|
||||
|
||||
|
||||
kv = LocalKVStore()
|
|
@ -0,0 +1,13 @@
|
|||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(name="Kortix")
|
||||
|
||||
|
||||
@mcp.tool
|
||||
async def get_weather(city: str) -> str:
|
||||
return f"The weather in {city} is windy."
|
||||
|
||||
|
||||
@mcp.tool
|
||||
async def get_wind_direction(city: str) -> str:
|
||||
return f"The wind direction in {city} is from the north."
|
|
@ -5,7 +5,7 @@ from .tools import AgentPressTools, MCPTools
|
|||
|
||||
|
||||
class Kortix:
|
||||
def __init__(self, api_key: str, api_url="http://localhost:8000/api"):
|
||||
def __init__(self, api_key: str, api_url="https://suna.so/api"):
|
||||
self._agents_client = agents.create_agents_client(api_url, api_key)
|
||||
self._threads_client = threads.create_threads_client(api_url, api_key)
|
||||
|
||||
|
|
Loading…
Reference in New Issue