# Develop with Content Agent

### Getting started

Content Agent gives you methods to use in your plugin such as `opencontent` to be able to do search/suggest requests from OpenContent by passing your search query for example!

Content Agent register it's own methods with [Dashboard Actions](https://docs.navigaglobal.com/dashboard-plugin/components/agent/actions)

You can use any of these actions in your plugin.

### Available actions

| ID                                    | Descriptions                                                                                                 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| com.naviga.content-agent:getProviders | An action to return all available provider names (from config)                                               |
| com.naviga.content-agent:getInstance  | An action returns the instance of content agent with Opencontent, Querystreamer, Infocaster and CCA methods. |

####

#### With getInstance action you will get an object that has four main instances:

* **opencontent**:
  * search -  *promise request.*
  * request -  *promise request*
  * suggest -  *promise request*
* **querystreamer**
  * activeStreams
  * createStream
  * deleteStream
* **infocaster**
  * activeSubscriptions
  * broadcast
  * subscribe
  * unsubscribe
* **cca**
  * Tools
    * ConvertToNewsml
    * ConvertToDocument
  * Files
    * GetStatus
    * GetArtifact
    * GetDownloadStatus
    * CreateUpload
    * CreateDownload
  * NewsML
    * GetNewsMLDocument
    * WriteNewsMLDocument
    * DeleteNewsMLDocument
    * NewsMLDocumentExists
  * Documents
    * GetDocument
    * WriteDocument
    * DeleteDocument
    * DocumentExists

### An example to how to get Content Agent instance

In your plugin you can import **getAction** from Plugin, so you can "import" Content Agent actions to your plugin.

{% tabs %}
{% tab title="Hook component" %}

```jsx
import { useRef, useState, useEffect } from 'react'
import { Plugin } from '@root'

const { getAction } = Plugin

const MyAwesomeComponent = props => {
    const CA = useRef()

    const [ready, setReady] = useState(false)
    
    useEffect(() => {
        const getInstance = getAction('com.naviga.content-agent:getInstance')
        const Instance = getInstance()
        
        CA.current = new Instance({
            onStatusChange: caReady => {
                setReady(caReady)
            }
        })
    }, [])
}
```

{% endtab %}

{% tab title="Class component" %}

```jsx
import { Component } from 'react'
import { Plugin } from '@root'

const { getAction } = Plugin

class MyAwesomeComponent extends Component {
    constructor(props) {
        super(props)
        
        this.CA = null
        
        this.state = {
            ready: false
        }
    }
    
    componentDidMount() {
        const getInstance = getAction('com.naviga.content-agent:getInstance')
        const Instance = getInstance()
        
        this.CA = new Instance({
            onStatusChange: caReady => {
                this.setState({
                    ready: caReady
                })
            }
        })
    }
}
```

{% endtab %}
{% endtabs %}

Here we used `com.naviga.content-agent:getInstance` action to get and initiate our CA instance, and listening on CA status changes with `onStatusChange`&#x20;

### Open Content

To access Open Content you call `CA.opencontent()` with the name of content provider you want to use (from config).

Access to `search` and `suggest` is simplified by two helper functions, but any OC REST API endpoint can be reached using the `request` function. The functions returns promises.

Open Content API Documentation can be found at \
url-to-open-content-server:8080/opencontent/apidocs/

#### Search

```javascript
const searchQuery = {
    q: "*:*"
}

CA.opencontent('im-demo').search(searchQuery).then(searchResult => {
    console.log(searchResult)
})
```

#### Suggest

```javascript
const suggestQuery = {
    'field': ['Authors'],
    'incompleteWord': ['P'],
    'type': 'ngram'
}

CA.opencontent('im-demo').suggest(suggestQuery).then(suggestResult => {
    console.log(suggestResult)
})
```

#### Generic OC API request

```javascript
const params = {
    'endpoint': 'eventlog',
    'method': 'GET',
    'qs': {
      'event' : -1
    }
}

CA.opencontent('im-demo').request(params).then(eventlogRes => {
    console.log(eventlogRes)
})
```

{% hint style="info" %}
search, suggest and request actions works the same as accessing them from CA.opencontent

by passing the provider as first argument and the request params as a second argument
{% endhint %}

### QueryStreamer

To handle streams in QueryStreamer you call `CA.querystreamer()` with the name of content provider you want to use (from config).

createStream and deleteStream is enabled on this instance.

[QueryStreamer API Documentation](https://querystreamer.lcc.infomaker.io/documentation)

[ElasticSearch Query Format Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/_introducing_the_query_language.html)

#### Create stream

When calling create stream, pass a request object and a callback function as parameters. This will return a promise that resolves with a stream ID. New events will land in the callback function you provided.

```javascript
const BUNDLE = "@plugin_bundle";
const VERSION = "@plugin_version";

const onStreamEvent = (event) => {
    const ocEvent = event.data.payload.result
    const noLongerMatching = event.data.payload.parameters.noLongerMatchingQuery
}

const req = {
    query : {
        query_string: {
            query : '*:*'
        }
    },
    config : {
        'notifyOnNoLongerMatchingQuery' : true
    },
    meta : {
        origin : {  // Add bundle and version to meta.origin. This helps when troubleshooting.
            bundle : BUNDLE,
            version : VERSION
        }
    }
}

const querystreamer = this.lcc.querystreamer('im-demo')
const updateStreamId = res => {
    // This will be called when a stream resumes after a disconnect as well
    // as initially with a temporary streamId in order to be able to clean up
    // if connection is broken before stream is fully setup
    this.streamId = res.streamId
}

return querystreamer.createStream(req, onStreamEvent, updateStreamId).then(res => {
    this.streamId = res.streamId
})
```

#### Delete stream

```javascript
CA.querystreamer('im-demo').deleteStream(STREAM_ID)
```

#### Cleanup

When a stream is no longer needed, **delete** it.

Please don't forget call `deleteStream(streamId)`&#x20;

* If you are creating a stream in a class component you can delete the stream when your component unmounted with `componentWillUnmount`.
* If you are creating a stream in a hook component you can delete the stream when your component unmounted with returning a function with `useEffect`&#x20;
* If you are creating a stream in the Agent you can delete the stream when your Agent close with `close`&#x20;

{% hint style="info" %}
You can handle events easily with querystreamer by passing qsInstance to [QueryEventWrapper](https://github.com/Infomaker/Dashboard-Plugin/wiki/ViewUtil#queryeventwrapper)
{% endhint %}

###

### Content Creation API (CCA)

In order to communicate with the Content Creation API you'll need to have added the [baseUrl to the cca part in the configuration](/content-agent/admin/config.md#example-using-cca-integration) as well as added [valid client credentials.](/content-agent/admin/config.md#example-using-client-credentials)

When this is done you're free to utilise the Content Creation API and the different endpoints, which you can read more about [here](https://docs.navigaglobal.com/cca-api-documentation/api).

```javascript
/**
*    A basic example of utilising CCA GetDocument
*/

const CCA = CA.cca('content-provider')

const document = await CCA.Documents.GetDocument({
    UUID: '1f672ac4-86ff-4a34-a264-80f26324be09'
})
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.navigaglobal.com/content-agent/developer/develop-with-content-agent.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
