Lingue is a base ontology for communication between heterogeneous intelligent agents. This document describes how IBIS (Issue-Based Information Systems) integrates with Lingue to enable structured deliberation while maintaining human-readable communication as the primary interface.
The fundamental design principle is that human-readable natural language is the default and primary communication mode. IBIS structure and RDF representations are optional enhancements that agents can negotiate when mutually beneficial.
┌─────────────────────────────────────┐
│ XMPP MUC (Human-readable layer) │
│ "I propose we use CoAP..." │
│ "Here's why that makes sense..." │
└─────────────────────────────────────┘
│ │
│ │ (optional structured exchange)
▼ ▼
┌─────────────────────────────────────┐
│ Lingue Protocol Negotiation │
│ "Hey, you speak IBIS-RDF?" │
│ "Yes! Let's exchange structured" │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Structured Data Exchange │
│ (IBIS RDF, complete arguments) │
└─────────────────────────────────────┘
A lingue-capable agent is a stateful software construct which implements:
@prefix lng: <http://purl.org/stuff/lingue/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix ibis: <https://vocab.methodandstructure.com/ibis#> .
:Agent1 a foaf:Agent ;
foaf:name "Sensor Monitor Bot" ;
lng:supports lng:XMPP, lng:HTTP ;
lng:understands ibis:, dcterms:, skos: ;
lng:preferredFormat "text/turtle" ;
lng:deliberationStyle :metaTransparent .
The system uses standard XMPP without custom extensions:
<message>, <iq>, <presence> stanzaspayload elements for structured mode/mime metadata; empty <body> allowed for status-only updates<message to="room@conference.example.org" type="groupchat">
<body>I think we should migrate to CoAP for the sensor network</body>
</message>
<iq type="get" to="agent2@example.org">
<query xmlns="http://jabber.org/protocol/disco#info"/>
</iq>
<iq type="result" from="agent2@example.org">
<query xmlns="http://jabber.org/protocol/disco#info">
<feature var="http://purl.org/stuff/lingue/ibis-rdf"/>
<feature var="http://purl.org/stuff/lingue/ask-tell"/>
</query>
</iq>
<message to="agent2@example.org" type="chat">
<body>I see you support Lingue IBIS. Would you like structured exchange?</body>
</message>
<message to="agent2@example.org" type="chat">
<body>Sending structured IBIS data...</body>
<payload xmlns="http://purl.org/stuff/lingue/" mime="text/turtle" mode="http://purl.org/stuff/lingue/IBISText">
<![CDATA[
@prefix ibis: <https://vocab.methodandstructure.com/ibis#> .
:pos-001 a ibis:Position ;
ibis:responds-to :issue-12 ;
rdfs:label "Migrate to CoAP" ;
ibis:supported-by :arg-efficiency, :arg-iot-standard .
:arg-efficiency a ibis:Argument ;
ibis:supports :pos-001 ;
rdfs:label "40% less overhead than HTTP" .
]]>
</payload>
</message>
<message to="room@conference.example.org" type="groupchat">
<body>Agent2 and I exchanged structured technical analysis.
Summary of our deliberation:
- Issue: Migration to CoAP (issue-12)
- Position: Yes, migrate (pos-001)
- Supporting Arguments:
* 40% less overhead than HTTP
* RFC 7252 standard compliance
* Better for constrained IoT devices
Full RDF available on request.</body>
</message>
Agents recognize and generate IBIS structure through natural language:
| Natural Language | IBIS Element |
|---|---|
| "What should we do about X?" | Issue |
| "How can we solve Y?" | Issue |
| "I propose we..." | Position |
| "Let's try..." | Position |
| "That makes sense because..." | Supporting Argument |
| "This works well due to..." | Supporting Argument |
| "However, there's a problem..." | Objecting Argument |
| "The downside is..." | Objecting Argument |
Agent1: "**Issue**: How should we handle authentication?
I see three options:
1. OAuth2 (standard, but complex)
2. API keys (simple, less secure)
3. mTLS (secure, requires PKI)
What do others think?"
[Agent internally structures this as:
Issue → 3 Positions]
# Agent posits an Issue
TELL {
:issue1 a ibis:Issue ;
rdfs:label "Should we use HTTP or MQTT for sensor data?" ;
dct:creator :Agent1 ;
dct:created "2025-12-15T10:30:00Z"^^xsd:dateTime .
}
# Agent requests positions on an issue
ASK {
?position ibis:responds-to :issue1 ;
a ibis:Position ;
rdfs:label ?label ;
dct:creator ?creator .
}
# Complete IBIS subnet exchange
:Agent1 lng:tells :Agent2 {
:issue-42 a ibis:Issue ;
rdfs:label "Sensor repair prioritization strategy?" ;
ibis:concerns :systemMaintenance .
:pos-critical a ibis:Position ;
ibis:responds-to :issue-42 ;
rdfs:label "Prioritize by criticality score" ;
dct:creator :Agent1 .
:arg-safety a ibis:Argument ;
ibis:supports :pos-critical ;
rdfs:label "Safety-critical sensors must be prioritized" .
:pos-geographic a ibis:Position ;
ibis:responds-to :issue-42 ;
rdfs:label "Prioritize by geographic proximity" ;
dct:creator :Agent1 .
:arg-efficiency a ibis:Argument ;
ibis:supports :pos-geographic ;
rdfs:label "Reduces technician travel time by 30%" .
}
Many agents will be LLM-powered. They use natural language processing for:
// LLM analyzes conversation to extract IBIS structure
async function detectIBISStructure(naturalLanguageText) {
const prompt = `
Analyze this conversation and identify IBIS elements:
- Issues (questions, problems to solve)
- Positions (proposed solutions)
- Arguments (supporting or objecting points)
Conversation: "${naturalLanguageText}"
Return as JSON with structure:
{
"issues": [...],
"positions": [...],
"arguments": [...]
}
`;
return await llm.complete(prompt);
}
// LLM converts detected structure to RDF
async function generateIBISRDF(ibisStructure) {
const prompt = `
Convert this IBIS structure to RDF Turtle format
using the IBIS vocabulary (https://vocab.methodandstructure.com/ibis#):
${JSON.stringify(ibisStructure)}
`;
return await llm.complete(prompt);
}
// LLM explains structured data naturally
async function explainIBISRDF(rdfGraph) {
const prompt = `
Explain this IBIS RDF graph in natural language
suitable for a chatroom audience:
${rdfGraph}
Make it conversational and clear.
`;
return await llm.complete(prompt);
}
Principle: Agents explain their structured exchanges to humans in the room.
:Agent a foaf:Agent ;
lng:transparencyLevel :metaTransparent .
# Options:
# :fullyPublic - All exchanges visible to everyone
# :metaTransparent - Agents explain what they're doing (DEFAULT)
# :private - Structured exchanges hidden (NOT RECOMMENDED)
class MetaTransparentAgent {
async handleStructuredExchange(fromAgent, ibisData) {
// 1. Process the structured data
const analysis = await this.analyzeIBIS(ibisData);
// 2. Generate human-readable summary
const summary = await this.llm.complete(`
Explain this IBIS exchange in simple terms:
${ibisData}
Make it conversational and mention:
- What we discussed
- What conclusions we reached
- Why those conclusions matter
`);
// 3. Post to room with transparency
await this.sendToRoom(`
🤖 Structured Exchange Complete
${fromAgent.name} and I just exchanged detailed IBIS data about: "${analysis.issue}"
${summary}
Technical details available on request. Just ask!
`);
}
}
The system works at multiple capability levels:
| Capability | Communication Mode | Use Case |
|---|---|---|
| Human only | Natural language text | Person in chatroom |
| Basic chatbot | NL + simple commands | Basic AI assistant |
| Lingue-aware | NL + protocol negotiation | Smart agent |
| Full Lingue+IBIS | NL + structured RDF | Sophisticated deliberation |
// TIA XMPP bot with Lingue + IBIS capability
import { Client } from '@xmpp/client';
import { parseRDF, serializeRDF } from './rdf-utils.js';
import { LLM } from './llm-client.js';
class LingueIBISBot {
constructor(jid, password) {
this.xmpp = new Client({ service: 'xmpp://server', username: jid, password });
this.llm = new LLM();
this.capabilities = new Set(['ibis-rdf', 'ask-tell', 'meta-transparent']);
}
async handleMessage(msg) {
// Always process natural language
const nlResponse = await this.generateNLResponse(msg.body);
// Check if sender is Lingue-capable
if (await this.isLingueCapable(msg.from)) {
// Detect IBIS structure in conversation
const ibisStructure = await this.detectIBISPattern(msg.body);
if (ibisStructure && ibisStructure.confidence > 0.7) {
// Offer structured exchange
await this.offerStructuredExchange(msg.from, ibisStructure);
}
}
// Always respond in human-readable form to room
return this.sendToRoom(nlResponse);
}
async offerStructuredExchange(agentJID, structure) {
// Private negotiation
await this.sendDirect(agentJID,
"I detected IBIS structure. Want to exchange RDF?");
// Wait for acceptance
const accepted = await this.waitForAcceptance(agentJID);
if (accepted) {
// Exchange complete RDF graph privately
const rdfGraph = await this.structureToRDF(structure);
await this.sendStructured(agentJID, rdfGraph);
// Meta-transparent explanation to room
const explanation = await this.explainExchange(structure);
await this.sendToRoom(`
🤖 Just exchanged structured IBIS data with ${agentJID}
${explanation}
Ask me for details if you're curious!
`);
}
}
async detectIBISPattern(text) {
const prompt = `
Analyze this text for IBIS patterns (Issues, Positions, Arguments).
Return confidence score (0-1) and detected structure.
Text: "${text}"
`;
return await this.llm.complete(prompt, { format: 'json' });
}
async isLingueCapable(jid) {
// XEP-0030 Service Discovery
const disco = await this.xmpp.iqCaller.request(
xml('iq', { type: 'get', to: jid },
xml('query', { xmlns: 'http://jabber.org/protocol/disco#info' })
)
);
const features = disco.getChild('query').getChildren('feature');
return features.some(f =>
f.attrs.var === 'http://purl.org/stuff/lingue/ibis-rdf'
);
}
}
// Usage
const bot = new LingueIBISBot('bot@example.org', 'password');
bot.joinRoom('deliberation@conference.example.org');
# Stored in triple store accessible to all agents
:network-2025-12-15 a ibis:Network ;
dct:title "Sensor System Design Deliberation" ;
dct:created "2025-12-15T09:00:00Z"^^xsd:dateTime ;
ibis:hasIssue :issue-1, :issue-2, :issue-3 .
:issue-1 a ibis:Issue ;
rdfs:label "How should we handle authentication?" ;
ibis:response :pos-oauth, :pos-apikeys, :pos-mtls .
// Each agent maintains local IBIS cache
class IBISCache {
constructor() {
this.store = new N3.Store();
}
async syncWithPeer(peerJID) {
// Request peer's IBIS data
const peerData = await this.requestIBIS(peerJID);
// Merge into local store
this.store.addQuads(parseRDF(peerData));
}
}
:Agent1 a foaf:Agent ;
lng:cacheStrategy :hybrid ;
lng:persistsTo <https://kb.example.org/ibis/> ;
lng:cacheTTL "P7D"^^xsd:duration . # 7 days
# Privacy controls to be defined
:StructuredExchange a lng:ExchangeEvent ;
lng:privacyLevel :private ; # or :public, :group, :pairwise
lng:visibleTo :Agent1, :Agent2 ;
lng:summarizeFor :room-participants .
Note: Privacy mechanisms are intentionally left open for future design decisions based on use case requirements.
A minimal implementation must support:
:Agent lng:understands ibis: .
:Agent1 lng:tells :Agent2 { :issue1 a ibis:Issue ; ... }
:Agent1 lng:asks :Agent2 { ?pos ibis:responds-to :issue1 }
This is a living document. Updates and refinements will be made as implementation proceeds.