Installation

Install the Nomos TypeScript SDK using npm or yarn:
npm install nomos-sdk
yarn add nomos-sdk
pnpm add nomos-sdk

Quick Start

Here’s a simple example to get you started:
import { NomosClient } from 'nomos-sdk';

async function main() {
  // Create client (no authentication required if server allows)
  const client = new NomosClient('http://localhost:8000');

  try {
    // Check server health
    const health = await client.healthCheck();
    console.log(`Server status: ${health.status}`);

    // Start a session-based conversation
    const session = await client.createSession(true);
    console.log(`Agent: ${JSON.stringify(session.message)}`);

    // Send a message
    const response = await client.sendMessage(session.session_id, 'Hello!');
    console.log(`Agent: ${JSON.stringify(response.message)}`);

    // End the session
    await client.endSession(session.session_id);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

main().catch(console.error);

Authentication

The SDK supports multiple authentication methods:

No Authentication

If your Nomos server doesn’t require authentication:
const client = new NomosClient('http://localhost:8000');

JWT Authentication

const client = new NomosClient({
  baseUrl: 'http://localhost:8000',
  auth: {
    type: 'jwt',
    token: 'your-jwt-token'
  }
});

API Key Authentication

const client = new NomosClient({
  baseUrl: 'http://localhost:8000',
  auth: {
    type: 'api_key',
    token: 'your-api-key'
  }
});

Dynamic Authentication

You can also set authentication after creating the client:
const client = new NomosClient('http://localhost:8000');

// Set authentication
client.setAuth({
  type: 'jwt',
  token: 'your-token'
});

// Clear authentication
client.clearAuth();

Usage Patterns

Session-based Conversations

Session-based conversations allow the server to maintain conversation state:
const client = new NomosClient('http://localhost:8000');

// Create a new session with initial message
const session = await client.createSession(true);
console.log(`Session ID: ${session.session_id}`);
console.log(`Agent: ${JSON.stringify(session.message)}`);

// Continue the conversation
const response1 = await client.sendMessage(session.session_id, 'Hello!');
console.log(`Agent: ${JSON.stringify(response1.message)}`);

const response2 = await client.sendMessage(session.session_id, 'How can you help me?');
console.log(`Agent: ${JSON.stringify(response2.message)}`);

// Get conversation history
const history = await client.getSessionHistory(session.session_id);
console.log(`History: ${history.history.length} messages`);

// End the session
await client.endSession(session.session_id);

Stateless Chat

Stateless chat allows you to maintain conversation state on the client side:
const client = new NomosClient('http://localhost:8000');

// Start with an empty session
let response = await client.chat({ user_input: 'Hello!' });
let sessionData = response.session_data;

console.log(`Agent: ${JSON.stringify(response.response)}`);

// Continue conversation by passing session data
response = await client.chat({
  user_input: 'Tell me more about your capabilities',
  session_data: sessionData
});

// Update session data for next message
sessionData = response.session_data;
console.log(`Agent: ${JSON.stringify(response.response)}`);

// Check for tool output (debugging)
if (response.tool_output) {
  console.log(`Tool output: ${response.tool_output}`);
}

With Authentication

import { NomosClient, NomosAuthError } from 'nomos-sdk';

const client = new NomosClient({
  baseUrl: 'https://your-nomos-server.com',
  auth: {
    type: 'jwt',
    token: process.env.NOMOS_JWT_TOKEN
  }
});

try {
  const session = await client.createSession(true);
  const response = await client.sendMessage(session.session_id, 'Hello!');
  await client.endSession(session.session_id);
} catch (error) {
  if (error instanceof NomosAuthError) {
    switch (error.status) {
      case 401:
        console.error('Authentication failed - check your token');
        break;
      case 403:
        console.error('Access forbidden - insufficient permissions');
        break;
      case 429:
        console.error('Rate limit exceeded - slow down requests');
        break;
    }
  } else {
    console.error('Other error:', error.message);
  }
}

API Reference

NomosClient

Main client class for interacting with Nomos agents.

Constructor

new NomosClient(config?: string | NomosClientConfig)
Parameters:
  • config: Base URL string or configuration object
Configuration Object:
interface NomosClientConfig {
  baseUrl?: string;
  auth?: AuthConfig;
}

interface AuthConfig {
  type: 'jwt' | 'api_key';
  token: string;
}

Methods

healthCheck()
Check the health status of the API server.
const health = await client.healthCheck();
// Returns: { status: "healthy", timestamp: 1234567890 }
createSession(initiate?: boolean)
Create a new session.
const session = await client.createSession(true);
// Returns: { session_id: string, message: Record<string, unknown> }
sendMessage(sessionId: string, message: string)
Send a message to an existing session.
const response = await client.sendMessage(sessionId, 'Hello!');
// Returns: { session_id: string, message: Record<string, unknown> }
getSessionHistory(sessionId: string)
Get conversation history for a session.
const history = await client.getSessionHistory(sessionId);
// Returns: { session_id: string, history: Array<Message | Summary | StepIdentifier> }
endSession(sessionId: string)
End a session.
await client.endSession(sessionId);
// Returns: { message: string }
chat(request: ChatRequest, verbose?: boolean)
Send a chat message with optional session data for stateless chat.
const response = await client.chat({
  user_input: 'Hello!',
  session_data: sessionData
}, true); // verbose = true for debugging
// Returns: ChatResponse object
setAuth(auth: AuthConfig)
Set authentication configuration.
client.setAuth({ type: 'jwt', token: 'your-token' });
clearAuth()
Clear authentication configuration.
client.clearAuth();
generateToken(payload: Record<string, unknown>)
Generate a JWT token (development only).
const tokenResponse = await client.generateToken({ user_id: 'test' });
// Returns: { access_token: string, token_type: string }

Type Definitions

Message

interface Message {
  role: string;
  content: string;
}

SessionResponse

interface SessionResponse {
  session_id: string;
  message: Record<string, unknown>;
}

SessionData

interface SessionData {
  session_id: string;
  current_step_id: string;
  history: Array<Message | Summary | StepIdentifier>;
  flow_state?: FlowState;
}

ChatRequest

interface ChatRequest {
  user_input?: string;
  session_data?: SessionData;
}

ChatResponse

interface ChatResponse {
  response: Record<string, unknown>;
  tool_output?: string | null;
  session_data: SessionData;
}

NomosAuthError

class NomosAuthError extends Error {
  constructor(message: string, public status?: number);
}

Error Handling

The SDK provides specific error types for different scenarios:
import { NomosClient, NomosAuthError } from 'nomos-sdk';

const client = new NomosClient({
  baseUrl: 'https://your-nomos-server.com',
  auth: { type: 'jwt', token: 'your-token' }
});

try {
  const response = await client.createSession();
} catch (error) {
  if (error instanceof NomosAuthError) {
    switch (error.status) {
      case 401:
        console.error('Authentication failed - check your token');
        break;
      case 403:
        console.error('Access forbidden - insufficient permissions');
        break;
      case 429:
        console.error('Rate limit exceeded - slow down requests');
        break;
      default:
        console.error(`Auth error: ${error.message}`);
    }
  } else {
    console.error('Unexpected error:', error.message);
  }
}

Environment Variables

For security, use environment variables for sensitive tokens:
# .env file
NOMOS_API_URL=https://your-nomos-server.com
NOMOS_JWT_TOKEN=your-jwt-token
NOMOS_API_KEY=your-api-key
const client = new NomosClient({
  baseUrl: process.env.NOMOS_API_URL,
  auth: {
    type: 'jwt',
    token: process.env.NOMOS_JWT_TOKEN
  }
});

Examples

Basic Session Example

import { NomosClient } from 'nomos-sdk';

async function basicExample() {
  const client = new NomosClient('http://localhost:8000');

  try {
    // Create and start a session
    const session = await client.createSession(true);
    console.log(`Session created: ${session.session_id}`);
    console.log(`Agent says: ${JSON.stringify(session.message)}`);

    // Send messages
    const response1 = await client.sendMessage(session.session_id, 'Hello!');
    console.log(`Agent: ${JSON.stringify(response1.message)}`);

    const response2 = await client.sendMessage(session.session_id, 'How can you help me?');
    console.log(`Agent: ${JSON.stringify(response2.message)}`);

    // Get history
    const history = await client.getSessionHistory(session.session_id);
    console.log(`Conversation has ${history.history.length} messages`);

    // End session
    await client.endSession(session.session_id);
    console.log('Session ended');
  } catch (error) {
    console.error('Error:', error.message);
  }
}

basicExample();

Stateless Chat Example

import { NomosClient } from 'nomos-sdk';

async function chatExample() {
  const client = new NomosClient('http://localhost:8000');

  try {
    // Start conversation
    let response = await client.chat({ user_input: 'Hello!' });
    let sessionData = response.session_data;
    console.log(`Agent: ${JSON.stringify(response.response)}`);

    // Continue conversation
    response = await client.chat({
      user_input: 'What can you do?',
      session_data: sessionData
    });
    sessionData = response.session_data;
    console.log(`Agent: ${JSON.stringify(response.response)}`);

    // Use verbose mode for debugging
    response = await client.chat({
      user_input: 'Tell me more',
      session_data: sessionData
    }, true); // verbose = true

    if (response.tool_output) {
      console.log(`Tool output: ${response.tool_output}`);
    }
  } catch (error) {
    console.error('Chat error:', error.message);
  }
}

chatExample();

Authenticated Example

import { NomosClient, NomosAuthError } from 'nomos-sdk';

async function authenticatedExample() {
  const client = new NomosClient({
    baseUrl: 'https://your-nomos-server.com',
    auth: {
      type: 'jwt',
      token: process.env.NOMOS_JWT_TOKEN
    }
  });

  try {
    // Check server health first
    const health = await client.healthCheck();
    console.log(`Server status: ${health.status}`);

    // Use the client normally
    const session = await client.createSession(true);
    const response = await client.sendMessage(session.session_id, 'Hello!');
    await client.endSession(session.session_id);
  } catch (error) {
    if (error instanceof NomosAuthError) {
      console.error(`Auth error (${error.status}): ${error.message}`);
    } else {
      console.error('Error:', error.message);
    }
  }
}

authenticatedExample();

React Component Example

import React, { useState, useCallback } from 'react';
import { NomosClient, SessionData } from 'nomos-sdk';

const ChatComponent: React.FC = () => {
  const [client] = useState(() => new NomosClient('http://localhost:8000'));
  const [messages, setMessages] = useState<Array<{role: string, content: string}>>([]);
  const [sessionData, setSessionData] = useState<SessionData | null>(null);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);

  const sendMessage = useCallback(async () => {
    if (!input.trim() || loading) return;

    const userMessage = { role: 'user', content: input };
    setMessages(prev => [...prev, userMessage]);
    setInput('');
    setLoading(true);

    try {
      const response = await client.chat({
        user_input: input,
        session_data: sessionData
      });

      const agentMessage = {
        role: 'agent',
        content: JSON.stringify(response.response)
      };

      setMessages(prev => [...prev, agentMessage]);
      setSessionData(response.session_data);
    } catch (error) {
      console.error('Chat error:', error);
    } finally {
      setLoading(false);
    }
  }, [client, input, sessionData, loading]);

  return (
    <div className="chat-container">
      <div className="messages">
        {messages.map((msg, index) => (
          <div key={index} className={`message ${msg.role}`}>
            <strong>{msg.role}:</strong> {msg.content}
          </div>
        ))}
      </div>

      <div className="input-area">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
          disabled={loading}
          placeholder="Type your message..."
        />
        <button onClick={sendMessage} disabled={loading || !input.trim()}>
          {loading ? 'Sending...' : 'Send'}
        </button>
      </div>
    </div>
  );
};

export default ChatComponent;

Node.js CLI Tool

import { NomosClient } from 'nomos-sdk';
import * as readline from 'readline';

async function createCLITool() {
  const client = new NomosClient({
    baseUrl: 'http://localhost:8000',
    auth: {
      type: 'api_key',
      token: process.env.NOMOS_API_KEY!
    }
  });

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });

  console.log('🤖 Nomos CLI Chat Tool');
  console.log('Type "quit" to exit\n');

  try {
    // Start session
    const session = await client.createSession(true);
    console.log(`Agent: ${JSON.stringify(session.message)}\n`);

    const askQuestion = () => {
      rl.question('You: ', async (input) => {
        if (input.toLowerCase() === 'quit') {
          await client.endSession(session.session_id);
          console.log('Goodbye!');
          rl.close();
          return;
        }

        try {
          const response = await client.sendMessage(session.session_id, input);
          console.log(`Agent: ${JSON.stringify(response.message)}\n`);
        } catch (error) {
          console.error('Error:', error.message);
        }

        askQuestion();
      });
    };

    askQuestion();
  } catch (error) {
    console.error('Failed to start:', error.message);
    rl.close();
  }
}

createCLITool().catch(console.error);

Express.js API Integration

import express from 'express';
import { NomosClient, NomosAuthError } from 'nomos-sdk';

const app = express();
app.use(express.json());

const client = new NomosClient({
  baseUrl: 'http://localhost:8000',
  auth: {
    type: 'jwt',
    token: process.env.NOMOS_JWT_TOKEN!
  }
});

// Session-based chat endpoint
app.post('/api/chat/:sessionId', async (req, res) => {
  try {
    const { sessionId } = req.params;
    const { message } = req.body;

    const response = await client.sendMessage(sessionId, message);
    res.json(response);
  } catch (error) {
    if (error instanceof NomosAuthError) {
      res.status(error.status || 401).json({ error: error.message });
    } else {
      res.status(500).json({ error: 'Chat failed' });
    }
  }
});

// Create new session
app.post('/api/sessions', async (req, res) => {
  try {
    const session = await client.createSession(true);
    res.json(session);
  } catch (error) {
    res.status(500).json({ error: 'Session creation failed' });
  }
});

// Stateless chat endpoint
app.post('/api/chat', async (req, res) => {
  try {
    const { user_input, session_data } = req.body;
    const response = await client.chat({ user_input, session_data });
    res.json(response);
  } catch (error) {
    res.status(500).json({ error: 'Chat failed' });
  }
});

// Health check
app.get('/api/health', async (req, res) => {
  try {
    const health = await client.healthCheck();
    res.json(health);
  } catch (error) {
    res.status(500).json({ error: 'Health check failed' });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Best Practices

  1. Handle authentication errors gracefully with proper error checking
  2. Use environment variables for sensitive tokens and API URLs
  3. End sessions properly to clean up server resources
  4. Implement retry logic with exponential backoff for production apps
  5. Use stateless chat for simple interactions, sessions for complex conversations
  6. Check server health before making requests in production
  7. Handle rate limiting by implementing proper backoff strategies
// Example: Retry logic with exponential backoff
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof NomosAuthError && error.status === 429) {
        if (attempt < maxRetries - 1) {
          const delay = baseDelay * Math.pow(2, attempt);
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }
      throw error;
    }
  }
  throw new Error('Max retries exceeded');
}

// Usage
const response = await withRetry(() =>
  client.sendMessage(sessionId, 'Hello!')
);

Browser Usage

The SDK works in browser environments with proper CORS configuration:
<!DOCTYPE html>
<html>
<head>
  <script type="module">
    import { NomosClient } from 'https://cdn.skypack.dev/nomos-sdk';

    const client = new NomosClient('http://localhost:8000');

    // Check if server is available
    try {
      const health = await client.healthCheck();
      console.log('Server is available:', health.status);

      // Use the client
      const response = await client.chat({ user_input: 'Hello from browser!' });
      console.log('Agent response:', response);
    } catch (error) {
      console.error('Error:', error.message);
    }
  </script>
</head>
</html>

TypeScript Configuration

For optimal TypeScript support:
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "strict": true
  }
}

Migration from v0.1.x

If you’re upgrading from version 0.1.x, see our Migration Guide for detailed instructions.

Quick Migration

Most v0.1.x code will work without changes:
// v0.1.x (still works)
const client = new NomosClient('http://localhost:8000');

// v0.2.x (new features)
const client = new NomosClient({
  baseUrl: 'http://localhost:8000',
  auth: { type: 'jwt', token: 'your-token' }
});

Troubleshooting

Common Issues

Authentication Errors
// Check your token and server configuration
try {
  await client.createSession();
} catch (error) {
  if (error instanceof NomosAuthError && error.status === 401) {
    console.log('Token may be expired or invalid');
  }
}
Module Resolution (Node.js)
// If you encounter import issues:
const { NomosClient } = require('nomos-sdk'); // CommonJS

// Or with dynamic imports:
const { NomosClient } = await import('nomos-sdk'); // ESM
CORS Issues (Browser)
// Ensure your Nomos server has proper CORS headers
// Check server configuration for allowed origins
Rate Limiting
// Implement proper backoff when hitting rate limits
if (error instanceof NomosAuthError && error.status === 429) {
  // Wait before retrying
  await new Promise(resolve => setTimeout(resolve, 1000));
}

Contributing

We welcome contributions to the Nomos TypeScript SDK! Please see our contributing guide for more information.

Support

For questions and support:

Changelog

v0.2.0 (Latest)

  • ✅ Added JWT and API key authentication support
  • ✅ Enhanced error handling with NomosAuthError
  • ✅ Added health check endpoint
  • ✅ Added verbose mode for chat debugging
  • ✅ Added token generation for development
  • ✅ Improved TypeScript types and documentation
  • ✅ Backward compatible with v0.1.x code

v0.1.0

  • 🚀 Initial release with basic session and chat functionality