diff --git a/src/go/internal/agent/remotecommand.go b/src/go/internal/agent/remotecommand.go
new file mode 100644
index 00000000000..05ed4e3e956
--- /dev/null
+++ b/src/go/internal/agent/remotecommand.go
@@ -0,0 +1,7 @@
+package agent
+
+type RemoteCommand struct {
+	Id      uint64 `json:"id"`
+	Command string `json:"command"`
+	Wait    int    `json:"wait"`
+}
diff --git a/src/go/internal/agent/resultcache/memorycache.go b/src/go/internal/agent/resultcache/memorycache.go
index e98b8d32a94..c87b76dc12c 100644
--- a/src/go/internal/agent/resultcache/memorycache.go
+++ b/src/go/internal/agent/resultcache/memorycache.go
@@ -200,6 +200,11 @@ func (c *MemoryCache) write(r *plugin.Result) {
 	}
 }
 
+func (c *MemoryCache) writeCommand(cr *CommandResult) {
+	// TODO: cache result
+	log.Debugf("cache command(%d) result:%s error:%s", cr.ID, cr.Result, cr.Error)
+}
+
 func (c *MemoryCache) run() {
 	defer log.PanicHook()
 	c.Debugf("starting memory cache")
@@ -214,6 +219,8 @@ func (c *MemoryCache) run() {
 			c.flushOutput(v)
 		case *plugin.Result:
 			c.write(v)
+		case *CommandResult:
+			c.writeCommand(v)
 		case *agent.AgentOptions:
 			c.updateOptions(v)
 		}
diff --git a/src/go/internal/agent/resultcache/resultcache.go b/src/go/internal/agent/resultcache/resultcache.go
index fad82eb31dc..d18fe164afd 100644
--- a/src/go/internal/agent/resultcache/resultcache.go
+++ b/src/go/internal/agent/resultcache/resultcache.go
@@ -23,11 +23,11 @@
 // specified output interface in json format when requested or cache is full.
 // The cache limits are specified by configuration file (BufferSize). If cache
 // limits are reached the following logic is applied to new results:
-// * non persistent results replaces either oldest result of the same item, or
-//   oldest non persistent result if item was not yet cached.
-// * persistent results replaces oldest non persistent result if the total number
-//   of persistent results is less than half maximum cache size. Otherwise the result
-//   is appended, extending cache beyond configured limit.
+//   - non persistent results replaces either oldest result of the same item, or
+//     oldest non persistent result if item was not yet cached.
+//   - persistent results replaces oldest non persistent result if the total number
+//     of persistent results is less than half maximum cache size. Otherwise the result
+//     is appended, extending cache beyond configured limit.
 //
 // Because of asynchronous nature of the communications it's not possible for
 // result cache to return error if it cannot accept new persistent result. So
@@ -36,7 +36,6 @@
 // can lead to more results written than cache limits allow. However it's not a
 // big problem because cache buffer is not static and will be extended as required.
 // The cache limit (BufferSize) is treated more like recommendation than hard limit.
-//
 package resultcache
 
 import (
@@ -95,6 +94,17 @@ type Uploader interface {
 	Session() (s string)
 }
 
+type CommandResult struct {
+	ID     uint64
+	Result string
+	Error  error
+}
+
+type Writer interface {
+	plugin.ResultWriter
+	WriteCommand(cr *CommandResult)
+}
+
 // common cache data
 type cacheData struct {
 	log.Logger
@@ -115,6 +125,10 @@ func (c *cacheData) Write(result *plugin.Result) {
 	c.input <- result
 }
 
+func (c *cacheData) WriteCommand(cr *CommandResult) {
+	c.input <- cr
+}
+
 // TODO: will be used once the runtime configuration reload is implemented
 func (c *cacheData) UpdateOptions(options *agent.AgentOptions) {
 	c.input <- options
diff --git a/src/go/internal/agent/scheduler/client.go b/src/go/internal/agent/scheduler/client.go
index 491b77c4cf8..52f9d53fb7f 100644
--- a/src/go/internal/agent/scheduler/client.go
+++ b/src/go/internal/agent/scheduler/client.go
@@ -30,6 +30,7 @@ import (
 	"git.zabbix.com/ap/plugin-support/log"
 	"git.zabbix.com/ap/plugin-support/plugin"
 	"zabbix.com/internal/agent"
+	"zabbix.com/internal/agent/resultcache"
 	"zabbix.com/pkg/glexpr"
 	"zabbix.com/pkg/zbxlib"
 )
@@ -51,8 +52,9 @@ type pluginInfo struct {
 // client represents source of items (metrics) to be queried.
 // Each server for active checks is represented by a separate client.
 // There is a predefined clients to handle:
-//    all single passive checks (client id 1)
-//    all internal checks (resolving HostnameItem, HostMetadataItem, HostInterfaceItem) (client id 0)
+//
+//	all single passive checks (client id 1)
+//	all internal checks (resolving HostnameItem, HostMetadataItem, HostInterfaceItem) (client id 0)
 type client struct {
 	// Client id. Predefined clients have ids < 100, while clients active checks servers (ServerActive)
 	// have auto incrementing id starting with 100.
@@ -64,7 +66,9 @@ type client struct {
 	// server global regular expression bundle
 	globalRegexp unsafe.Pointer
 	// plugin result sink, can be nil for bulk passive checks (in future)
-	output plugin.ResultWriter
+	output resultcache.Writer
+	// remote command expiration times
+	commands map[uint64]time.Time
 }
 
 // ClientAccessor interface exports client data required for scheduler tasks.
@@ -271,6 +275,59 @@ func (c *client) addRequest(p *pluginAgent, r *plugin.Request, sink plugin.Resul
 	return nil
 }
 
+// command registry cleanup
+// TODO: add all client hourly command cleanup to manager
+func (c *client) commandCleanup() {
+	now := time.Now()
+	for id, expire := range c.commands {
+		if now.After(expire) {
+			delete(c.commands, id)
+		}
+	}
+}
+
+func (c *client) addCommand(p *pluginAgent, id uint64, params []string, sink resultcache.Writer, now time.Time) {
+
+	if _, ok := c.commands[id]; ok {
+		return
+	}
+	c.commands[id] = now.Add(time.Hour)
+
+	var info *pluginInfo
+	var ok bool
+	if info, ok = c.pluginsInfo[p]; !ok {
+		info = &pluginInfo{}
+	}
+
+	if p.refcount == 0 {
+		task := &configuratorTask{
+			taskBase: taskBase{plugin: p, active: true},
+			options:  &agent.Options,
+		}
+		_ = task.reschedule(now)
+		p.enqueueTask(task)
+	}
+
+	task := &commandTask{
+		taskBase: taskBase{plugin: p, active: true},
+		id:       id,
+		params:   params,
+		output:   sink,
+	}
+
+	_ = task.reschedule(now)
+	p.enqueueTask(task)
+
+	// update plugin usage information
+	if info.used.IsZero() {
+		p.refcount++
+		c.pluginsInfo[p] = info
+	}
+	info.used = now
+
+	log.Debugf("scheduled remote command(%d) '%s'", id, params[0])
+}
+
 // cleanup releases unused uplugins. For external clients it's done after update,
 // while for internal clients once per hour.
 func (c *client) cleanup(plugins map[string]*pluginAgent, now time.Time) (released []*pluginAgent) {
@@ -358,12 +415,13 @@ func (c *client) updateExpressions(expressions []*glexpr.Expression) {
 }
 
 // newClient creates new client
-func newClient(id uint64, output plugin.ResultWriter) (b *client) {
+func newClient(id uint64, output resultcache.Writer) (b *client) {
 	b = &client{
 		id:          id,
 		exporters:   make(map[uint64]exporterTaskAccessor),
 		pluginsInfo: make(map[*pluginAgent]*pluginInfo),
 		output:      output,
+		commands:    make(map[uint64]time.Time),
 	}
 
 	return
diff --git a/src/go/internal/agent/scheduler/manager.go b/src/go/internal/agent/scheduler/manager.go
index 9416e34caba..18ce61ca783 100644
--- a/src/go/internal/agent/scheduler/manager.go
+++ b/src/go/internal/agent/scheduler/manager.go
@@ -34,6 +34,7 @@ import (
 	"zabbix.com/internal/agent"
 	"zabbix.com/internal/agent/alias"
 	"zabbix.com/internal/agent/keyaccess"
+	"zabbix.com/internal/agent/resultcache"
 	"zabbix.com/internal/monitor"
 	"zabbix.com/pkg/glexpr"
 	"zabbix.com/pkg/itemutil"
@@ -63,10 +64,20 @@ type Manager struct {
 // updateRequest contains list of metrics monitored by a client and additional client configuration data.
 type updateRequest struct {
 	clientID                   uint64
-	sink                       plugin.ResultWriter
+	sink                       resultcache.Writer
 	firstActiveChecksRefreshed bool
 	requests                   []*plugin.Request
+	commands                   []*agent.RemoteCommand
 	expressions                []*glexpr.Expression
+	now                        time.Time
+}
+
+// commandRequest contains list of remote commands
+type commandRequest struct {
+	clientID uint64
+	sink     resultcache.Writer
+	commands []*agent.RemoteCommand
+	now      time.Time
 }
 
 // queryRequest contains status/debug query request.
@@ -81,8 +92,9 @@ type queryRequestUserParams struct {
 }
 
 type Scheduler interface {
-	UpdateTasks(clientID uint64, writer plugin.ResultWriter, firstActiveChecksRefreshed bool,
-		expressions []*glexpr.Expression, requests []*plugin.Request)
+	UpdateTasks(clientID uint64, writer resultcache.Writer, firstActiveChecksRefreshed bool,
+		expressions []*glexpr.Expression, requests []*plugin.Request, now time.Time)
+	UpdateCommands(clientID uint64, writer resultcache.Writer, commands []*agent.RemoteCommand, now time.Time)
 	FinishTask(task performer)
 	PerformTask(key string, timeout time.Duration, clientID uint64) (result string, err error)
 	Query(command string) (status string)
@@ -143,7 +155,7 @@ func (m *Manager) cleanupClient(c *client, now time.Time) {
 
 // processUpdateRequest processes client update request. It's being used for multiple requests
 // (active checks on a server) and also for direct requets (single passive and internal checks).
-func (m *Manager) processUpdateRequest(update *updateRequest, now time.Time) {
+func (m *Manager) processUpdateRequest(update *updateRequest) {
 	log.Debugf("[%d] processing update request (%d requests)", update.clientID, len(update.requests))
 
 	// immediately fail direct checks and ignore bulk requests when shutting down
@@ -153,7 +165,7 @@ func (m *Manager) processUpdateRequest(update *updateRequest, now time.Time) {
 				update.sink.Write(&plugin.Result{
 					Itemid: update.requests[0].Itemid,
 					Error:  errors.New("Cannot obtain item value during shutdown process."),
-					Ts:     now,
+					Ts:     update.now,
 				})
 			} else {
 				log.Warningf("[%d] direct checks can contain only single request while received %d requests",
@@ -192,7 +204,7 @@ func (m *Manager) processUpdateRequest(update *updateRequest, now time.Time) {
 			if !ok {
 				err = fmt.Errorf("Unknown metric %s", key)
 			} else {
-				err = c.addRequest(p, r, update.sink, now, update.firstActiveChecksRefreshed)
+				err = c.addRequest(p, r, update.sink, update.now, update.firstActiveChecksRefreshed)
 			}
 		}
 
@@ -203,7 +215,7 @@ func (m *Manager) processUpdateRequest(update *updateRequest, now time.Time) {
 					tacc.task().deactivate()
 				}
 			}
-			update.sink.Write(&plugin.Result{Itemid: r.Itemid, Error: err, Ts: now})
+			update.sink.Write(&plugin.Result{Itemid: r.Itemid, Error: err, Ts: update.now})
 			log.Debugf("[%d] cannot monitor metric \"%s\": %s", update.clientID, r.Key, err.Error())
 			continue
 		}
@@ -215,7 +227,49 @@ func (m *Manager) processUpdateRequest(update *updateRequest, now time.Time) {
 		}
 	}
 
-	m.cleanupClient(c, now)
+	m.cleanupClient(c, update.now)
+}
+
+func (m *Manager) processCommandRequest(update *commandRequest) {
+	log.Debugf("[%d] processing command request (%d commands)", update.clientID, len(update.commands))
+
+	var c *client
+	var ok bool
+	if c, ok = m.clients[update.clientID]; !ok {
+		log.Debugf("[%d] registering new client", update.clientID)
+		c = newClient(update.clientID, update.sink)
+		m.clients[update.clientID] = c
+	}
+
+	for _, rc := range update.commands {
+		var wait string
+		if rc.Wait == 1 {
+			wait = "wait"
+		} else {
+			wait = "nowait"
+		}
+		params := []string{rc.Command, wait}
+
+		if !keyaccess.CheckRules("system.run", params) {
+			log.Warningf("Remote command '%s' is not allowed", rc.Command)
+			continue
+		}
+
+		if p, ok := m.plugins["system.run"]; ok {
+			c.addCommand(p, rc.Id, params, update.sink, update.now)
+
+			if !p.queued() {
+				heap.Push(&m.pluginQueue, p)
+			} else {
+				m.pluginQueue.Update(p)
+			}
+
+		} else {
+			// TODO: handle system.run unavailablity
+		}
+	}
+
+	m.cleanupClient(c, update.now)
 }
 
 // processQueue processes queued plugins/tasks
@@ -394,7 +448,10 @@ run:
 			}
 			switch v := u.(type) {
 			case *updateRequest:
-				m.processUpdateRequest(v, time.Now())
+				m.processUpdateRequest(v)
+				m.processQueue(time.Now())
+			case *commandRequest:
+				m.processCommandRequest(v)
 				m.processQueue(time.Now())
 			case performer:
 				m.processFinishRequest(v)
@@ -550,14 +607,23 @@ func (m *Manager) Stop() {
 	m.input <- nil
 }
 
-func (m *Manager) UpdateTasks(clientID uint64, writer plugin.ResultWriter, firstActiveChecksRefreshed bool,
-	expressions []*glexpr.Expression, requests []*plugin.Request) {
-
+func (m *Manager) UpdateTasks(clientID uint64, writer resultcache.Writer, firstActiveChecksRefreshed bool,
+	expressions []*glexpr.Expression, requests []*plugin.Request, now time.Time) {
 	m.input <- &updateRequest{clientID: clientID,
 		sink:                       writer,
 		requests:                   requests,
 		expressions:                expressions,
 		firstActiveChecksRefreshed: firstActiveChecksRefreshed,
+		now:                        now,
+	}
+}
+
+func (m *Manager) UpdateCommands(clientID uint64, writer resultcache.Writer, commands []*agent.RemoteCommand, now time.Time) {
+	m.input <- &commandRequest{
+		clientID: clientID,
+		sink:     writer,
+		commands: commands,
+		now:      now,
 	}
 }
 
@@ -567,6 +633,10 @@ func (r resultWriter) Write(result *plugin.Result) {
 	r <- result
 }
 
+func (r resultWriter) WriteCommand(cr *resultcache.CommandResult) {
+	log.Errf("remote commands are not supported by single task requets")
+}
+
 func (r resultWriter) Flush() {
 }
 
@@ -584,7 +654,7 @@ func (m *Manager) PerformTask(key string, timeout time.Duration, clientID uint64
 
 	w := make(resultWriter, 1)
 
-	m.UpdateTasks(clientID, w, false, nil, []*plugin.Request{{Key: key, LastLogsize: &lastLogsize, Mtime: &mtime}})
+	m.UpdateTasks(clientID, w, false, nil, []*plugin.Request{{Key: key, LastLogsize: &lastLogsize, Mtime: &mtime}}, time.Now())
 
 	select {
 	case r := <-w:
diff --git a/src/go/internal/agent/scheduler/task.go b/src/go/internal/agent/scheduler/task.go
index fbc87c34241..e983aea858d 100644
--- a/src/go/internal/agent/scheduler/task.go
+++ b/src/go/internal/agent/scheduler/task.go
@@ -28,6 +28,7 @@ import (
 	"git.zabbix.com/ap/plugin-support/log"
 	"git.zabbix.com/ap/plugin-support/plugin"
 	"zabbix.com/internal/agent"
+	"zabbix.com/internal/agent/resultcache"
 	"zabbix.com/pkg/itemutil"
 	"zabbix.com/pkg/zbxlib"
 )
@@ -35,6 +36,7 @@ import (
 // task priority within the same second is done by setting nanosecond component
 const (
 	priorityConfiguratorTaskNs = iota
+	priorityCommandTaskNs      = iota
 	priorityStarterTaskNs
 	priorityCollectorTaskNs
 	priorityWatcherTaskNs
@@ -475,3 +477,49 @@ func (t *configuratorTask) getWeight() int {
 func (t *configuratorTask) isItemKeyEqual(itemkey string) bool {
 	return false
 }
+
+// commandTask executes remote commands received with active requestes
+type commandTask struct {
+	taskBase
+	id     uint64
+	params []string
+	output resultcache.Writer
+}
+
+func (t *commandTask) isRecurring() bool {
+	return false
+}
+func (t *commandTask) perform(s Scheduler) {
+	// execute remote command
+	go func() {
+		e := t.plugin.impl.(plugin.Exporter)
+
+		var cr *resultcache.CommandResult
+
+		if ret, err := e.Export("system.run", t.params, nil); err == nil {
+			if ret != nil {
+				cr = &resultcache.CommandResult{
+					ID:     t.id,
+					Result: itemutil.ValueToString(ret),
+				}
+			}
+		} else {
+			log.Debugf("failed to execute remote command '%s' error: '%s'",
+				t.params[0], err.Error())
+
+			cr = &resultcache.CommandResult{
+				ID:    t.id,
+				Error: err,
+			}
+		}
+
+		t.output.WriteCommand(cr)
+		t.output.Flush()
+
+	}()
+}
+
+func (t *commandTask) reschedule(now time.Time) (err error) {
+	t.scheduled = time.Unix(now.Unix(), priorityCommandTaskNs)
+	return
+}
diff --git a/src/go/internal/agent/serverconnector/serverconnector.go b/src/go/internal/agent/serverconnector/serverconnector.go
index fb3a76848a7..ae677b92929 100644
--- a/src/go/internal/agent/serverconnector/serverconnector.go
+++ b/src/go/internal/agent/serverconnector/serverconnector.go
@@ -76,11 +76,12 @@ type activeChecksRequest struct {
 }
 
 type activeChecksResponse struct {
-	Response       string               `json:"response"`
-	Info           string               `json:"info"`
-	ConfigRevision uint64               `json:"config_revision,omitempty"`
-	Data           []*plugin.Request    `json:"data"`
-	Expressions    []*glexpr.Expression `json:"regexp"`
+	Response       string                 `json:"response"`
+	Info           string                 `json:"info"`
+	ConfigRevision uint64                 `json:"config_revision,omitempty"`
+	Data           []*plugin.Request      `json:"data"`
+	Commands       []*agent.RemoteCommand `json:"commands"`
+	Expressions    []*glexpr.Expression   `json:"regexp"`
 }
 
 type agentDataResponse struct {
@@ -160,15 +161,18 @@ func (c *Connector) refreshActiveChecks() {
 	log.Debugf("[%d] In refreshActiveChecks() from %s", c.clientID, c.addresses)
 	defer log.Debugf("[%d] End of refreshActiveChecks() from %s", c.clientID, c.addresses)
 
-	if a.HostInterface, err = processConfigItem(c.taskManager, time.Duration(c.options.Timeout)*time.Second, "HostInterface",
-		c.options.HostInterface, c.options.HostInterfaceItem, agent.HostInterfaceLen, agent.LocalChecksClientID); err != nil {
+	if a.HostInterface, err = processConfigItem(c.taskManager, time.Duration(c.options.Timeout)*time.Second,
+		"HostInterface", c.options.HostInterface, c.options.HostInterfaceItem, agent.HostInterfaceLen,
+		agent.LocalChecksClientID); err != nil {
 		log.Errf("cannot get host interface: %s", err)
+
 		return
 	}
 
 	if a.HostMetadata, err = processConfigItem(c.taskManager, time.Duration(c.options.Timeout)*time.Second, "HostMetadata",
 		c.options.HostMetadata, c.options.HostMetadataItem, agent.HostMetadataLen, agent.LocalChecksClientID); err != nil {
 		log.Errf("cannot get host metadata: %s", err)
+
 		return
 	}
 
@@ -223,18 +227,24 @@ func (c *Connector) refreshActiveChecks() {
 		return
 	}
 
+	now := time.Now()
+
 	if response.Response != "success" {
 		if len(response.Info) != 0 {
 			log.Errf("[%d] no active checks on server [%s]: %s", c.clientID, c.addresses[0], response.Info)
 		} else {
 			log.Errf("[%d] no active checks on server [%s]", c.clientID, c.addresses[0])
 		}
-		c.taskManager.UpdateTasks(c.clientID, c.resultCache.(plugin.ResultWriter), c.firstActiveChecksRefreshed,
-			[]*glexpr.Expression{}, []*plugin.Request{})
+		c.taskManager.UpdateTasks(c.clientID, c.resultCache.(resultcache.Writer), c.firstActiveChecksRefreshed,
+			[]*glexpr.Expression{}, []*plugin.Request{}, now)
 		c.firstActiveChecksRefreshed = true
 		return
 	}
 
+	if response.Commands != nil {
+		c.taskManager.UpdateCommands(c.clientID, c.resultCache.(resultcache.Writer), response.Commands, now)
+	}
+
 	if response.Data == nil {
 		if c.configRevision == 0 {
 			log.Errf("[%d] cannot parse list of active checks from [%s]: data array is missing", c.clientID,
@@ -321,8 +331,9 @@ func (c *Connector) refreshActiveChecks() {
 		}
 	}
 
-	c.taskManager.UpdateTasks(c.clientID, c.resultCache.(plugin.ResultWriter), c.firstActiveChecksRefreshed,
-		response.Expressions, response.Data)
+	c.taskManager.UpdateTasks(c.clientID, c.resultCache.(resultcache.Writer), c.firstActiveChecksRefreshed,
+		response.Expressions, response.Data, now)
+
 	c.firstActiveChecksRefreshed = true
 }
 
diff --git a/src/go/pkg/itemutil/value.go b/src/go/pkg/itemutil/value.go
index f308cb692bf..24a655ab3ad 100644
--- a/src/go/pkg/itemutil/value.go
+++ b/src/go/pkg/itemutil/value.go
@@ -29,44 +29,51 @@ import (
 
 const StateNotSupported = 1
 
-func ValueToResult(itemid uint64, ts time.Time, u interface{}) (result *plugin.Result) {
-	var value string
+func ValueToString(u interface{}) string {
 	switch v := u.(type) {
-	case *plugin.Result:
-		return v
-	case plugin.Result:
-		return &v
 	case string:
-		value = u.(string)
+		return u.(string)
 	case *string:
-		value = *u.(*string)
+		return *u.(*string)
 	case int:
-		value = strconv.FormatInt(int64(v), 10)
+		return strconv.FormatInt(int64(v), 10)
 	case int8:
-		value = strconv.FormatInt(int64(v), 10)
+		return strconv.FormatInt(int64(v), 10)
 	case int16:
-		value = strconv.FormatInt(int64(v), 10)
+		return strconv.FormatInt(int64(v), 10)
 	case int32:
-		value = strconv.FormatInt(int64(v), 10)
+		return strconv.FormatInt(int64(v), 10)
 	case int64:
-		value = strconv.FormatInt(v, 10)
+		return strconv.FormatInt(v, 10)
 	case uint:
-		value = strconv.FormatUint(uint64(v), 10)
+		return strconv.FormatUint(uint64(v), 10)
 	case uint8:
-		value = strconv.FormatUint(uint64(v), 10)
+		return strconv.FormatUint(uint64(v), 10)
 	case uint16:
-		value = strconv.FormatUint(uint64(v), 10)
+		return strconv.FormatUint(uint64(v), 10)
 	case uint32:
-		value = strconv.FormatUint(uint64(v), 10)
+		return strconv.FormatUint(uint64(v), 10)
 	case uint64:
-		value = strconv.FormatUint(v, 10)
+		return strconv.FormatUint(v, 10)
 	case float32:
-		value = strconv.FormatFloat(float64(v), 'f', 6, 64)
+		return strconv.FormatFloat(float64(v), 'f', 6, 64)
 	case float64:
-		value = strconv.FormatFloat(v, 'f', 6, 64)
+		return strconv.FormatFloat(v, 'f', 6, 64)
 	default:
 		// note that this conversion is slow and it's better to return known value type
-		value = fmt.Sprintf("%v", u)
+		return fmt.Sprintf("%v", u)
+	}
+}
+
+func ValueToResult(itemid uint64, ts time.Time, u interface{}) (result *plugin.Result) {
+	var value string
+	switch v := u.(type) {
+	case *plugin.Result:
+		return v
+	case plugin.Result:
+		return &v
+	default:
+		value = ValueToString(u)
 	}
 	return &plugin.Result{Itemid: itemid, Value: &value, Ts: ts}
 }
