Metadata-Version: 2.4
Name: private-me-semantic-kernel-xlink
Version: 0.1.1
Summary: Semantic Kernel integration for xLink identity-based authentication (orchestration + planning + memory, 603× faster M2M auth)
Author: Private.Me Contributors
License: SEE LICENSE IN LICENSE.md
Project-URL: Homepage, https://private.me
Project-URL: Documentation, https://private.me/docs/semantic-kernel-xlink
Project-URL: Repository, https://github.com/private-me/platform
Project-URL: Issues, https://github.com/private-me/platform/issues
Keywords: semantic-kernel,microsoft-ai,xlink,identity,authentication,ai-agents,orchestration,planning,memory,m2m,zero-config
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: private-me-aci-core>=0.3.1
Requires-Dist: private-me-shared>=0.1.1
Requires-Dist: private-me-ux-helpers>=0.1.1
Requires-Dist: semantic-kernel>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"

# Private.Me xLink for Semantic Kernel (Python)

**Identity-based authentication for Semantic Kernel plugins and orchestration.**

Python bindings for `@private.me/semantic-kernel-xlink`. Build Semantic Kernel AI applications with cryptographic identity instead of API keys. Zero-config setup, enterprise-grade access control, no cascading failures.

## Installation

### Prerequisites

This package requires both the Node.js module and Python bindings:

```bash
# 1. Install Node.js package
npm install @private.me/semantic-kernel-xlink semantic-kernel

# 2. Install Python bindings
pip install private-me-semantic-kernel-xlink
```

**Requirements:**
- Python 3.9+
- Node.js 18+ (for backend)
- npm (for Node.js package installation)
- Semantic Kernel SDK

## Quick Start

```python
from private_me import semantic_kernel_xlink

# Create kernel plugin (generates identity automatically)
plugin = await semantic_kernel_xlink.create_plugin(
    name='my-plugin',
    verbose=True
)

# Execute skill with identity auth (no credentials!)
result = await plugin.call(
    skill='text-summarization',
    params={'text': 'Long document to summarize...'}
)

if result.ok:
    print(f"Summary: {result.value}")
```

**That's it.** No API keys, no OAuth, no configuration files.

## API Reference

### `create_plugin(name: str, policy: Dict[str, Any] = None, verbose: bool = False) -> SemanticKernelXLinkPlugin`

Create Semantic Kernel plugin with identity-based authentication.

**Parameters:**
- `name` (str): Plugin name for identification
- `policy` (Dict[str, Any], optional): Policy configuration
  - `allowed_skills` (List[str]): Whitelist of allowed skills
  - `max_plugin_calls` (int): Maximum plugin calls before refresh
  - `execution_timeout` (int): Timeout in milliseconds (default: 30000)
- `verbose` (bool): Enable logging (default: False)

**Returns:**
- `SemanticKernelXLinkPlugin`: Plugin instance with cryptographic identity

**Example:**
```python
plugin = await semantic_kernel_xlink.create_plugin(
    name='research-agent',
    policy={
        'allowed_skills': ['summarization', 'text-analysis'],
        'max_plugin_calls': 100,
        'execution_timeout': 30000
    },
    verbose=True
)
```

### `SemanticKernelXLinkPlugin.get_did() -> str`

Get plugin's decentralized identifier.

**Returns:**
- `str`: DID (e.g., `did:key:z6Mk...`)

**Example:**
```python
did = plugin.get_did()
print(f"Plugin Identity: {did}")
```

### `SemanticKernelXLinkPlugin.call(skill: str, params: Dict[str, Any]) -> Result`

Execute Semantic Kernel skill with identity authentication.

**Parameters:**
- `skill` (str): Skill name to execute
- `params` (Dict[str, Any]): Skill parameters

**Returns:**
- `Result`: Result object with `.ok` (bool) and `.value` or `.error`

**Raises:**
- `RuntimeError`: If Node.js backend fails
- `PolicyViolationError`: If skill execution violates policy

**Example:**
```python
result = await plugin.call(
    skill='text-summarization',
    params={'text': 'Research paper abstract...', 'max_length': 100}
)

if result.ok:
    print(f"Summary: {result.value}")
else:
    print(f"Error: {result.error['title']}")
```

### `SemanticKernelXLinkPlugin.send(to: str, payload: Dict[str, Any]) -> Result`

Send message to another agent using xLink identity.

**Parameters:**
- `to` (str): Recipient's DID
- `payload` (Dict[str, Any]): Message payload

**Returns:**
- `Result`: Result object with `.ok` (bool)

**Raises:**
- `RuntimeError`: If message delivery fails

**Example:**
```python
await plugin.send(
    to='did:key:z6Mkrecipient...',
    payload={
        'type': 'task-complete',
        'results': ['Finding 1', 'Finding 2']
    }
)
```

### `SemanticKernelXLinkPlugin.receive() -> Result`

Receive messages sent to this plugin.

**Returns:**
- `Result`: Result object containing list of messages

**Example:**
```python
messages = await plugin.receive()
if messages.ok:
    for msg in messages.value:
        print(f"From: {msg['from']}")
        print(f"Payload: {msg['payload']}")
```

### `SemanticKernelXLinkPlugin.get_audit_log() -> List[Dict[str, Any]]`

Retrieve execution audit trail for compliance and monitoring.

**Returns:**
- `List[Dict[str, Any]]`: Audit log entries with timestamps, skills, status

**Example:**
```python
audit_log = plugin.get_audit_log()
for entry in audit_log:
    print(f"[{entry['timestamp']}] {entry['skill']}: {entry['status']}")
```

### `SemanticKernelXLinkPlugin.export_identity() -> Result`

Export identity for persistence across sessions.

**Returns:**
- `Result`: Result containing PKCS8 private key bytes

**Example:**
```python
export_result = await plugin.export_identity()
if export_result.ok:
    with open('plugin-identity.key', 'wb') as f:
        f.write(export_result.value)
```

### `from_identity(pkcs8: bytes, name: str, policy: Dict[str, Any] = None) -> Result`

Create plugin from existing identity.

**Parameters:**
- `pkcs8` (bytes): PKCS8 private key
- `name` (str): Plugin name
- `policy` (Dict[str, Any], optional): Policy configuration

**Returns:**
- `Result`: Result containing plugin with restored identity

**Example:**
```python
with open('plugin-identity.key', 'rb') as f:
    identity_bytes = f.read()

restore_result = await semantic_kernel_xlink.from_identity(
    pkcs8=identity_bytes,
    name='restored-plugin'
)

if restore_result.ok:
    restored_plugin = restore_result.value
    print(restored_plugin.get_did())  # Same DID as original
```

## Usage Examples

### Basic Skill Execution

```python
from private_me import semantic_kernel_xlink

# Create plugin
plugin = await semantic_kernel_xlink.create_plugin(name='assistant')

print(f"Plugin Identity: {plugin.get_did()}")

# Execute summarization skill
result = await plugin.call(
    skill='text-summarization',
    params={'text': 'Semantic Kernel is a lightweight SDK...'}
)

if result.ok:
    print(f"Summary: {result.value}")
else:
    print(f"Error: {result.error['detail']}")
```

### Policy-Enforced Plugin

```python
from private_me import semantic_kernel_xlink

# Create plugin with strict policy
plugin = await semantic_kernel_xlink.create_plugin(
    name='policy-enforced',
    policy={
        'allowed_skills': ['summarization', 'text-analysis'],
        'max_plugin_calls': 50,
        'execution_timeout': 30000
    }
)

# Allowed skill - succeeds
result = await plugin.call(
    skill='summarization',
    params={'text': 'Document content...'}
)
print(f"Allowed: {result.ok}")  # True

# Disallowed skill - policy violation
result = await plugin.call(
    skill='image-generation',
    params={'prompt': 'sunset'}
)
print(f"Blocked: {not result.ok}")  # True
print(f"Reason: {result.error['detail']}")  # "Skill not in allowedSkills list"
```

### Multi-Agent Orchestration

```python
from private_me import semantic_kernel_xlink

# Create orchestrator and worker agents
orchestrator = await semantic_kernel_xlink.create_plugin(name='orchestrator')
worker = await semantic_kernel_xlink.create_plugin(name='worker')

# Orchestrator assigns task to worker
await orchestrator.send(
    to=worker.get_did(),
    payload={
        'type': 'task-assignment',
        'task': 'analyze-data',
        'data': {'records': 1000}
    }
)

# Worker receives and processes task
messages = await worker.receive()
if messages.ok and len(messages.value) > 0:
    task = messages.value[0]['payload']
    print(f"Received task: {task['task']}")

    # Execute skill
    result = await worker.call(
        skill='data-analysis',
        params={'records': task['data']['records']}
    )

    # Send results back
    await worker.send(
        to=orchestrator.get_did(),
        payload={
            'type': 'task-complete',
            'results': result.value
        }
    )
```

### Identity Persistence

```python
from private_me import semantic_kernel_xlink
import os

# Create plugin and export identity
plugin = await semantic_kernel_xlink.create_plugin(name='persistent-agent')
original_did = plugin.get_did()

export_result = await plugin.export_identity()
if export_result.ok:
    with open('agent-identity.key', 'wb') as f:
        f.write(export_result.value)

# Later: restore plugin with same identity
with open('agent-identity.key', 'rb') as f:
    identity_bytes = f.read()

restore_result = await semantic_kernel_xlink.from_identity(
    pkcs8=identity_bytes,
    name='persistent-agent'
)

if restore_result.ok:
    restored_plugin = restore_result.value
    print(original_did == restored_plugin.get_did())  # True
```

### Audit Trail for Compliance

```python
from private_me import semantic_kernel_xlink

# Create plugin with audit enabled
plugin = await semantic_kernel_xlink.create_plugin(
    name='audited-agent',
    verbose=True
)

# Execute multiple skills
await plugin.call('summarization', {'text': 'Doc 1'})
await plugin.call('text-analysis', {'text': 'Doc 2'})
await plugin.call('translation', {'text': 'Doc 3', 'target': 'es'})

# Retrieve audit log
audit_log = plugin.get_audit_log()
print(f"Total executions: {len(audit_log)}")

for entry in audit_log:
    print(f"[{entry['timestamp']}] Skill: {entry['skill']}")
    print(f"  Status: {entry['status']}")
    print(f"  Duration: {entry['duration_ms']}ms")
```

### Error Handling with RFC 7807

```python
from private_me import semantic_kernel_xlink

plugin = await semantic_kernel_xlink.create_plugin(name='agent')

result = await plugin.call(
    skill='text-summarization',
    params={'text': 'Too short'}  # Invalid input
)

if not result.ok:
    # Structured error with field-level details
    error = result.error

    print(f"Error Type: {error['type']}")
    print(f"Title: {error['title']}")
    print(f"Detail: {error['detail']}")
    print(f"Instance: {error['instance']}")

    if 'invalid_params' in error:
        print("Invalid parameters:")
        for param in error['invalid_params']:
            print(f"  - {param['name']}: {param['reason']}")

    if 'fix' in error:
        print(f"Fix: {error['fix']}")
```

## Policy Configuration

Control plugin behavior with fine-grained policies:

| Policy Field | Type | Description |
|--------------|------|-------------|
| `allowed_skills` | List[str] | Whitelist of executable skills |
| `max_plugin_calls` | int | Maximum calls before identity refresh |
| `execution_timeout` | int | Timeout per skill call (milliseconds) |

**Example:**
```python
policy = {
    'allowed_skills': ['summarization', 'translation'],
    'max_plugin_calls': 100,
    'execution_timeout': 60000  # 1 minute
}

plugin = await semantic_kernel_xlink.create_plugin(
    name='policy-agent',
    policy=policy
)
```

## Architecture

This package uses a **wrapper pattern**:

```
Python App → Python Bindings → Node.js Backend → Semantic Kernel SDK
```

1. **Python layer**: Provides Pythonic API (`create_plugin()`, `call()`)
2. **Node.js backend**: Handles cryptographic operations (Ed25519, DID generation)
3. **Semantic Kernel integration**: Plugin execution, policy enforcement, audit logging

## Troubleshooting

### "Node.js module not found"

**Error:**
```
RuntimeError: Node.js module @private.me/semantic-kernel-xlink not found
```

**Solution:**
```bash
# Install Node.js package first
npm install @private.me/semantic-kernel-xlink semantic-kernel

# Verify installation
ls node_modules/@private.me/semantic-kernel-xlink
```

### "Node.js backend error"

**Error:**
```
RuntimeError: Node.js backend error: <message>
```

**Solution:**
- Check Node.js version (requires 18+): `node --version`
- Verify Node.js package installed: `npm list @private.me/semantic-kernel-xlink`
- Check Semantic Kernel installed: `npm list semantic-kernel`
- Review Node.js error message for details

### Policy violation errors

**Error:**
```
PolicyViolationError: Skill not in allowedSkills list
```

**Solution:**
- Verify skill name matches exactly (case-sensitive)
- Add skill to `allowed_skills` list in policy configuration
- Check skill is available in Semantic Kernel installation
- Review audit log to see which skills are being called

### Skill execution timeout

**Error:**
```
RuntimeError: Skill execution timeout after 30000ms
```

**Solution:**
- Increase `execution_timeout` in policy configuration
- Optimize skill parameters (reduce input size, lower max tokens)
- Check network connectivity to LLM provider
- Review skill implementation for performance issues

### Invalid identity errors

**Error:**
```
ValueError: Invalid PKCS8 private key format
```

**Solution:**
- Verify exported identity is complete (not truncated)
- Check file permissions allow reading identity file
- Ensure identity was exported via `export_identity()` method
- Verify identity bytes are not corrupted (checksum validation)

### Message delivery failures

**Error:**
```
RuntimeError: Message delivery failed: recipient not found
```

**Solution:**
- Verify recipient DID is valid (starts with `did:key:`)
- Ensure recipient plugin is running and connected
- Check network connectivity between agents
- Review xLink registry configuration

## Development

### Running Tests

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest -v

# Run with coverage
pytest -v --cov=private_me --cov-report=html
```

### Building

```bash
# Build wheel
python setup.py bdist_wheel

# Validate build
bash validate-build.sh
```

## Support

- **Documentation**: https://private.me/docs/semantic-kernel-xlink
- **White Paper**: https://private.me/docs/semantic-kernel-xlink.html
- **Email**: contact@private.me
- **GitHub**: https://github.com/xail-io/xail

## License

Proprietary - See LICENSE.md

---

**Questions?** Visit [private.me/docs/semantic-kernel-xlink](https://private.me/docs/semantic-kernel-xlink) for complete documentation.
