> ## Documentation Index
> Fetch the complete documentation index at: https://docs.idyllic.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Appendix B: Idyllic Reference

This appendix provides a quick reference for Idyllic constructs used throughout the book. Idyllic is notation for exploring ideas—the principles transfer to any implementation.

## Core Decorators

### @field

Marks a property as persisted and client-synced state.

```typescript theme={null}
export default class MySystem extends AgenticSystem {
  @field count = 0;                          // Primitive
  @field items: string[] = [];               // Array
  @field config: Record<string, any> = {};   // Object
  @field status: stream<string>('');         // Streaming value
}
```

**Behavior:**

* Automatically persisted across Durable Object hibernation
* Changes broadcast to all connected clients
* Supports all JSON-serializable types

### @action()

Marks a method as callable from outside the system.

```typescript theme={null}
@action()
async processInput(input: string): Promise<string> {
  // Implementation
  return result;
}
```

**Behavior:**

* Callable via WebSocket from clients
* Typed parameters and return values
* Automatically generates client types

### @tool()

Marks a method as available to the LLM for invocation.

```typescript theme={null}
@tool({
  description: 'Search the web for information on a topic'
})
async searchWeb(query: string): Promise<SearchResult[]> {
  // Implementation
}
```

**Parameters:**

* `description`: Explains what the tool does (shown to LLM)
* Optional: `permission: 'always' | 'confirm' | 'never'`

### @schedule()

Marks a method for periodic or scheduled execution.

```typescript theme={null}
@schedule('every 5 minutes')
async checkForUpdates() {
  // Runs every 5 minutes
}

@schedule('every day at 2am')
async dailyMaintenance() {
  // Runs once daily at 2 AM
}
```

**Schedule formats:**

* `'every N minutes'`
* `'every N hours'`
* `'every day at HH:MM'`
* `'every monday at HH:MM'`

## Streaming Values

### `stream<T>()`

Creates a streaming value that can be appended to incrementally.

```typescript theme={null}
@field output: stream<string>('');
@field items: stream<Item[]>([]);

// In a method:
this.output.append('chunk');       // Add to string
this.output.set('new value');      // Replace entirely
this.output.reset('');             // Clear to initial
const value = this.output.current(); // Get current value

this.items.set([...items, newItem]); // Update array
```

**Use cases:**

* Token-by-token LLM output
* Progress indicators
* Real-time logs

## Vector Store

### `VectorStore<T>`

Semantic storage with similarity search.

```typescript theme={null}
@field knowledge: VectorStore<{
  content: string;
  source: string;
  timestamp: number;
}>;

// Insert
await this.knowledge.insert({
  content: 'fact about topic',
  source: 'documentation',
  timestamp: Date.now()
});

// Search
const results = await this.knowledge.search(query, 5);
// Returns: { item: T, similarity: number }[]

// Get by ID
const item = await this.knowledge.get(id);

// Update
await this.knowledge.update(id, newItem);

// Delete
await this.knowledge.delete(id);
```

## System Lifecycle

### Initialization

```typescript theme={null}
export default class MySystem extends AgenticSystem {
  async initialize() {
    // Called once when system first created
    // Set up initial state
  }
}
```

### State Access

```typescript theme={null}
// Access system ID (stable across restarts)
const id = this.id;

// Access environment
const apiKey = this.env.API_KEY;
```

### State Synchronization

```typescript theme={null}
@action()
async longRunningTask() {
  this.status = 'starting';
  sync(); // Broadcast current state to clients

  await this.doWork();

  this.status = 'complete';
  sync(); // Broadcast again
}
```

## Client Integration

### React Hook

```typescript theme={null}
import { useSystem } from '@idyllic/react';

function MyComponent() {
  const {
    count,           // Field values
    status,          // Streaming value
    increment,       // Action method
    isConnected,     // Connection state
    error            // Any errors
  } = useSystem<MySystemClient>();

  return (
    <div>
      <p>Count: {count}</p>
      <p>Status: {status}</p>
      <button onClick={() => increment()}>+1</button>
    </div>
  );
}
```

### Streaming Values in React

```typescript theme={null}
function StreamingOutput() {
  const { output } = useSystem<MySystemClient>();

  // output updates in real-time as tokens arrive
  return <pre>{output}</pre>;
}
```

## LLM Integration

### Basic Completion

```typescript theme={null}
const response = await llm.complete([
  { role: 'system', content: 'You are a helpful assistant.' },
  { role: 'user', content: prompt }
]);
```

### With Tools

```typescript theme={null}
const response = await llm.complete(messages, {
  tools: [this.searchWeb, this.readFile]
});

// Response may include tool calls
if (response.toolCalls) {
  for (const call of response.toolCalls) {
    const result = await this[call.name](...call.arguments);
    messages.push({
      role: 'tool',
      content: JSON.stringify(result),
      toolCallId: call.id
    });
  }
}
```

### Streaming Completion

```typescript theme={null}
for await (const chunk of llm.stream(messages)) {
  this.output.append(chunk);
}
this.output.complete();
```

## Complete Example

```typescript theme={null}
import { AgenticSystem, field, action, tool, schedule, stream, VectorStore } from '@idyllic/core';

export default class ResearchAssistant extends AgenticSystem {
  // Persisted state
  @field messages: Message[] = [];
  @field knowledge: VectorStore<Knowledge>;

  // Streaming output
  @field thinking: stream<string>('');
  @field response: stream<string>('');

  // Configuration
  @field systemPrompt = 'You are a research assistant...';

  async initialize() {
    this.knowledge = new VectorStore();
  }

  @action()
  async chat(input: string) {
    this.messages.push({ role: 'user', content: input });
    this.thinking.reset('');
    this.response.reset('');

    // Retrieve relevant knowledge
    const relevant = await this.knowledge.search(input, 5);
    this.thinking.append('Found ' + relevant.length + ' relevant items\n');

    // Generate response
    for await (const chunk of llm.stream([
      { role: 'system', content: this.systemPrompt },
      { role: 'system', content: 'Relevant knowledge:\n' + relevant.map(r => r.item.content).join('\n') },
      ...this.messages
    ])) {
      this.response.append(chunk);
    }

    this.messages.push({ role: 'assistant', content: this.response.current() });
  }

  @tool({ description: 'Search the web' })
  async search(query: string): Promise<SearchResult[]> {
    // Implementation
  }

  @schedule('every day at 3am')
  async maintenance() {
    // Clean up old messages
    if (this.messages.length > 100) {
      this.messages = this.messages.slice(-50);
    }
  }
}

interface Message {
  role: 'user' | 'assistant' | 'system';
  content: string;
}

interface Knowledge {
  content: string;
  source: string;
}

interface SearchResult {
  title: string;
  url: string;
  snippet: string;
}
```
